すでに他の方々が紹介された内容の繰り返しばかりですが,勉強を兼ねた自分用のメモです。
自分用ではありますが,同じくらいのR歴の方のお役に立てばいいなと思います。
間違いなど、お気づきの場合は@imuyaoyiにご指摘いただければ幸いです。
library(ggplot2)
library(dplyr)
library(gridExtra)
library(scales)
library(grid)
library(pforeach)
Hist1 <- ggplot(iris, aes(x = Sepal.Length))+
geom_histogram()
Box1 <- ggplot(iris, aes(x = 1, y = Sepal.Length))+
geom_boxplot()+
coord_flip() # グラフを横向きにする
grid.arrange(Hist1, Box1, ncol = 1, # 1列に
nrow = 2) # 2行描く
箱ひげ図のy軸ラベルを丸っきり消してしまうと,ヒストグラムと揃えたはずのx軸がズレるので軸ラベルの色を白にして見えなくしました。
グラフ全体の外枠をつけるのに使用したgrid.rect関数はgridパッケージに含まれる関数です。
V <- iris$Sepal.Length
Bin = diff(range(V)/20) # 変数の値の幅を指定したい階級数で割って階級幅を求める
Mean = mean(V) # ヒストグラム用の平均値
Lim = c(min(V)-sd(V)/2, max(V)+sd(V)/2) # x軸の範囲(標準偏差の1/2分ながくする)
Hist2 <- ggplot(iris, aes(x = Sepal.Length))+
geom_histogram(binwidth = Bin, fill = "darkgray")+ # 階級幅 # ヒストグラムの色
geom_vline(xintercept = Mean, color = "black", size = 1)+ # 平均値の線を引く
coord_cartesian(xlim = Lim)+ # x軸範囲
theme_classic(base_size = 18)+ # 背景や軸を全体のテーマで設定 # フォントサイズ
theme(panel.grid.major = element_line(color = "lightgray"))+ # グリッドだけ個別に指定
labs(title = "Sepal.Length", x = "", y = "") # グラフタイトルと軸ラベル
Box2 <- ggplot(iris, aes(x = 1, y = Sepal.Length))+
geom_boxplot()+
coord_flip(ylim = Lim)+ # x軸範囲 #グラフの向きを変えたのでylimで指定する
theme_minimal(base_size = 18)+
theme(axis.text.y = element_text(color = "white"))+ # y軸ラベルのフォント色を白にして見えなくする
labs(x = "", y = "")
grid.arrange(Hist2, Box2, ncol = 1, nrow = 2, heights = c(4,1)) # heightsでグラフサイズの比率を指定
grid.rect(gp = gpar(fill = NA, lwd = 1, col = "gray")) # 外枠をつける
前にplot関数でやったことをggplot関数を使ってやります。
↑をHiRoshima.R#4で紹介した際,
ということなどをご指摘いただきましたので,それらを踏まえて次の手順で作業しました。
ggplot2を含む作図関数を自作するとき,次の2つのポイントに注意が必要です。
a.については,前回のplot関数を使った場合と同じで,ループ変数iに読み込ませるリストとして
列名よりも列番号で指定する方が扱いやすいため*このようにしています。
ggplot(iris, aes(x = Sepal.Length))+
geom_histogram()
ggplot(iris, aes(x = iris[,1]))+ # 列番号による変数指定
geom_histogram()
b.は,通常の,""のついていない変数名で指定するaes()ではなく,""のついた文字列形式の変数名で指定するaes_string()を使うということです。
ggplot(iris, aes(x = Sepal.Length))+
geom_histogram()
ggplot(iris, aes_string(x = "Sepal.Length"))+ # 文字列で変数指定
geom_histogram()
ggplotを含む関数を自作する場合,aes_string()を使ってに変数指定をしないとうまくいきませんでした。
# Fun1 <- function(data, i){
# ggplot(data, aes(x = data[,i]))+
# geom_histogram()
# }
# Fun1(iris, 1)
# Error in data[, i] : object of type 'closure' is not subsettable # エラーになる
Fun2 <- function(data, i){
ggplot(data, aes_string(x = colnames(data)[i]))+
geom_histogram()
}
Fun2(iris, 2) # OK!
pforeachパッケージのnpforeach関数を使って一括出力します。
ポイントは以下3つです。
pforeachパッケージを作成されたhoxo_mさんによる解説はこちらです。
for関数やforeachパッケージを使うとこんなかんじです。参考までに。。。
for(i in rep(1:length(Data),10)){
print(Fun3(Data, i))
}
foreach(i = rep(1:length(Data),10))%do%{
print(Fun3(Data, i))
}
HistBox <- function(data, i){
V = data[,i]
VName = colnames(data)[i]
Bin = diff(range(V))/20
Mean = mean(V)
Lim = c(min(V)-sd(V)/2, max(V)+sd(V)/2)
Hist <- ggplot(data, aes_string(x = VName))+
geom_histogram(binwidth = Bin, fill = "darkgray")+
geom_vline(xintercept = Mean, color = "black", size = 1)+
coord_cartesian(xlim = Lim)+
scale_y_continuous(labels = comma)+ # scalesパッケージを使用して
scale_x_continuous(labels = comma)+ # 数値を区切りカンマを入れる
theme_classic(base_size = 18)+
theme(panel.grid.major = element_line(color = "lightgray"))+
labs(title = VName, x = "", y = "")
Box <- ggplot(data, aes_string(x = 1, y = VName))+
geom_boxplot()+
coord_flip(ylim = Lim)+
scale_y_continuous(labels = comma)+
theme_minimal(base_size = 18)+
theme(axis.text.y = element_text(color = "lightgray"))+
labs(x = "", y = "")
grid.arrange(Hist, Box, ncol = 1, nrow = 2, heights = c(4,1))
grid.rect(gp = gpar(fill = NA, lwd = 1, col = "gray"))
}
Barplot <- function(data, i){
V = colnames(data)[i]
data %>%
dplyr::select_(V) %>%
dplyr::filter_(!is.na(V)) %>%
table %>% as.data.frame() %>%
ggplot(aes(x = . , y = Freq))+
geom_bar(stat = "identity")+
geom_text(aes(x = ., y = Freq, label = Freq, vjust = -0.5), size = 5)+
theme_classic(base_size = 18)+
theme(panel.grid.major = element_line(color = "white"),
plot.background = element_rect(color = "gray", size = 1))+
labs(title = V ,x = "", y = "")
}
npforeach(i = 1:ncol(iris) ,.final = invisible)({
if(is.factor(iris[,i])){
print(Barplot(iris,i)) # print()をつけないと出力できない
} else if(is.numeric(iris[,i])){
HistBox(iris, i)
}
})
dat <- as.data.frame(diamonds)
npforeach(i = 1:ncol(dat), .final = invisible)({
if(is.factor(dat[,i])){
dat[,i] <- as.factor(dat[,i])
print(Barplot(dat,i))
} else if(is.integer(dat[,i])|is.numeric(dat[,i])){
HistBox(dat, i)
}
})
観測度数の桁数が大きくなるとヒストグラムと箱ひげ図のx軸がずれる
diamondsデータのように観測度数の桁数が大きくなると,ヒストグラムだけy数値軸の幅が広くなり
グラフが右側にずれてしまうため,箱ひげ図とのx軸の位置がずれてしまいます。。。
y数値軸の幅を指定して固定するか,箱ひげ図のy数値軸をヒストグラムの方の桁数に合わせて値を大きくするか
とか考えたけど,できるかわからないし,いい方法が浮かびません(´・x・`)。。。
自作関数Barplotの方が複雑なのに説明をスルーした
dplyr組み込んだり,aes()じゃなくてaes_string()使ったり,
途中でtable()使って,さらにdata.frameに変換したりとカオスなのに
説明あきらめた(´・x・`)。。。 きっともっとうまいやり方があるに違いない。。
一度理想的な作図関数作って方法を確立してしまえば今後楽できると思ったけど,簡単にはいかないー