<- read.csv("practice.csv") d01
超初心者向けのRガイド
g. 各種グラフの雛形
1 全体の構成
2 Rでの調査データの可視化(Visualization)
以下では,演習用データの practice.csv ファイルを用いてグラフの描き方を例示する1。
標準関数は,基本的に with( ) で包んで使用する例で示す。
3 ヒストグラム
3.1 標準関数でのヒストグラム
with(d01,
hist(fincome)
)
with(d01,
hist(fincome,
main = "Q29 世帯収入",
sub = "(過去1年,税込み,年金・株・副収入等含む)",
xlab = "世帯収入(万円)",
ylab = "人数",
family = "serif", # Macでは "HiraKakuProN-W3"などを指定する。
col = "#00640060", # garkgreenの#006400に透過度60を指定
las = 1)
)
調査票の選択肢の幅の通りに区間を区切る。縦軸は人数ではなくなり密度になるのが問題。
後半は算術平均や中央値の位置を書き込むもので,単なる例。
様々なオプションを付けたhist( )
with(d01,
hist(fincome,
breaks = c(0, 50, 100, seq(150, 850, by = 100),
1000, 1250, 1500, 2000, 3000),
main = "Q29 世帯収入",
sub = "(過去1年,税込み,年金・株・副収入等含む)",
xlab = "世帯収入(万円)",
ylab = "密度",
yaxt = "n",
family = "serif", # Macでは "HiraKakuProN-W3"などを指定する。
col = "#556b2f30", # garkolivegreenに透過度60を指定
border = "#556b2f",
las = 2)
)
axis(side = 2,
at = c(0, 1),
labels = c("0", NA),
family = "serif",
las = 1)
# ここから先は,中央値や算術平均を書き込むためのもので必須ではない。
abline(v = mean(d01$fincome, na.rm = T),
col = "red",
lty = "dotted")
axis(side = 1,
at = mean(d01$fincome, na.rm = T),
labels = paste("mean", round(mean(d01$fincome, na.rm = T), 0)),
cex.axis = 0.8,
col.axis = "red",
family = "serif",
las = 2)
abline(v = median(d01$fincome, na.rm = T),
col = "blue",
lty = "dashed")
axis(side = 1,
at = median(d01$fincome, na.rm = T),
labels = paste("median", round(median(d01$fincome, na.rm = T), 0)),
cex.axis = 0.8,
col.axis = "blue",
family = "serif",
las = 2)
3.2 ggplotでのヒストグラム
Rでグラフを描くパッケイジとして絶大な人気を誇るggplot2。
base Rとは異なる独特の記法もあって最初はやや敷居が高く感じるが,覚えるにつれ,高品質でかつ高度な統計処理を施したグラフを,さまざまに好みのカスタマイズをして描く事が出来る様になる。
解説書や解説サイトも非常に多い。
基本関数はggplot( )であるが,パッケイジの名前はggplot2なので間違えないように。
installは,そのPC,そのversionのRに対して1回行えばよい(言い換えれば,base Rをupdateしたら追加パッケイジも再度installする事になる)。
library(ggplot2)はRを起動する毎に(ggplotを使用する前に)実行する。そのRセッションを終了するまでは有効。
install.packages("ggplots") # 最初に1回だけinstallする。
library(ggplot2) # R session毎に1回必要。
ggplotでは,color = や fill = で指定することで,グループごとのグラフを描く事が出来る。
<- by(d01$income, d01$SEX, mean, na.rm = T) mean.data
annotate( )でそれぞれの算術平均の値を書き込んでいるが,ここは余りうまくないので削除して良い。
ggplot(d01, aes(x = income,
color = SEX,
fill = SEX)) +
geom_histogram(position = "identity",
alpha = .5) +
geom_text(aes(y = ..count..,
label = ifelse(..count.. > 0, ..count.., ""),
col = SEX),
stat = "bin",
vjust = -0.5) +
geom_vline(xintercept = mean.data,
color = c("#F8766D", "#00BFC4"),
linetype = "dashed") +
labs(title = "男女別の個人年収",
subtitle = "東京・千葉・埼玉・神奈川 30-59歳",
caption = "2014年3モード比較調査",
x = "個人年収(万円)",
y = "人数",
color = "",
fill = "") +
theme_minimal() +
theme(legend.position = c(.8, .7)) +
annotate("text",
x = mean.data,
y = -4,
label = sprintf("mean %.0f", mean.data),
color = c("#F8766D", "#00BFC4"),
family = "serif")
4 棒グラフ
4.1 標準関数での棒グラフ
raw dataから棒グラフを描画する際には,変数をそのまま引数に与えてもダメで,集計したものを用いなければならない点に注意。
with(d01,
barplot(strata5)
)
<- with(d01, table(strata5))) (t01
strata5
1 2 3 4 5
4 119 170 69 14
序に少しオプションを追加する。
with(d01,
barplot(t01,
main = "5段階階層帰属意識の分布",
sub = "東京・千葉・埼玉・神奈川の30-59歳男女(2014年)",
xlab = "5段階階層帰属意識",
names = c("上", "中の上", "中の下", "下の上", "下の下"),
ylab = "人数",
family = "serif",
col = "#f0808080",
border = "#f08080ff",
las = 1)
)
barplot( )の中でtable( )で集計してみる。
with(d01,
barplot(table(strata5, SEX),
beside = T,
legend.text = c("上", "中の上", "中の下",
"下の上", "下の下"),
main = "5段階階層帰属意識の分布",
sub = "東京・千葉・埼玉・神奈川の30-59歳男女(2014年)",
xlab = "5段階階層帰属意識",
ylab = "人数",
family = "serif",
col = heat.colors(5),
border = heat.colors(5),
las = 1)
)
barplot( )の中でprop.table(table( ), margin = 2)で集計してみる。
with(d01,
barplot(prop.table(table(strata5, SEX), margin = 2),
beside = T,
legend.text = c("上", "中の上", "中の下",
"下の上", "下の下"),
main = "5段階階層帰属意識の分布",
sub = "東京・千葉・埼玉・神奈川の30-59歳男女(2014年)",
xlab = "5段階階層帰属意識",
ylab = "割合",
family = "serif",
col = topo.colors(5),
border = topo.colors(5),
las = 1)
)
いわゆる帯グラフ。割合を%にしてみた。
必要度は低いのだが,凡例legendに色々とオプションを付けて例示している。
with(d01,
barplot(prop.table(table(strata5, SEX), margin = 2)*100,
beside = F,
legend.text = c("上", "中の上", "中の下",
"下の上", "下の下"),
args.legend = list(x = 2.0,
y = 75,
xjust = 0,
box.col = NA,
cex = 0.9,
bg = "#f5f5dc80",
horiz = F,
border = NA),
main = "5段階階層帰属意識の分布",
sub = "東京・千葉・埼玉・神奈川の30-59歳男女(2014年)",
xlab = "5段階階層帰属意識",
ylab = "パーセント",
family = "serif",
col = terrain.colors(5),
border = "grey20",
las = 1)
)
4.2 ggplotでの棒グラフ
geom_barでは集計表を渡す必要は無い。
x軸からNAを除外するのに手間がかかる2。
度数を付記する為に geom_text を使う。
ggplot(d01, aes(x = STRATA5)) +
geom_bar(fill = "#0000cd60") +
geom_text(aes(y = ..count..,
label = ifelse(..count.. > 0, ..count.., "")),
stat = "count",
vjust = -0.2) +
scale_x_discrete(na.translate = F) +
labs(title = "階層帰属意識の分布",
subtitle = "30-59歳男女",
caption = "東京・千葉・埼玉・神奈川(2014年)",
x = "5段階階層帰属意識",
y = "人数") +
theme_light()
xにSEXを置いてfillにSTRATA5を指定する事で,男女の中での内訳として階層帰属意識を表示する。
position = “fill”としてy軸を上まで引き延ばして帯グラフとする。
NAの除外がなお一層面倒なので,データフレイムの指定を工夫してNAを除外している3。
ggplot(d01[!is.na(d01$STRATA5),],
aes(x = SEX, color = STRATA5, fill = STRATA5)) +
geom_bar(position = "fill", alpha = .2) +
geom_text(aes(label = ifelse(..count.. > 0, ..count.., "")),
stat = "count",
position = position_fill(vjust = 0.5)) +
scale_color_manual(values = c("brown", "darkgreen", "forestgreen",
"mediumblue", "lightskyblue")) +
scale_fill_manual(values = c("brown", "darkgreen", "forestgreen",
"mediumblue", "lightskyblue")) +
labs(title = "階層帰属意識の分布",
subtitle = "30-59歳男女",
caption = "東京・千葉・埼玉・神奈川(2014年)",
x = "",
y = "割合",
color = "階層帰属意識",
fill = "階層帰属意識") +
theme_light()
更にfacet_grid( )でMODE別に表示する。
ggplot(d01[!is.na(d01$STRATA5),],
aes(x = SEX, color = STRATA5, fill = STRATA5)) +
geom_bar(position = "fill", alpha = .2) +
geom_text(aes(label = ifelse(..count.. > 0, ..count.., "")),
stat = "count",
position = position_fill(vjust = 0.5)) +
scale_fill_manual(values = c("brown", "darkgreen", "forestgreen",
"mediumblue", "lightskyblue"),
na.translate = F) +
scale_color_manual(values = c("brown", "darkgreen", "forestgreen",
"mediumblue", "lightskyblue"),
na.translate = F) +
labs(title = "階層帰属意識の分布",
subtitle = "30-59歳男女",
caption = "東京・千葉・埼玉・神奈川(2014年)",
x = "",
y = "割合",
color = "階層帰属意識",
fill = "階層帰属意識") +
theme_light() +
facet_grid(~ MODE)
5 散布図
5.1 標準関数での散布図
with(d01,
plot(strata10, happy)
)
with(d01,
plot(strata10, happy,
bty = "n",
las = 1,
main = "階層帰属意識と幸福感",
sub = "",
xlab = "10段階階層帰属意識(1 下← →上 10)",
ylab = "幸福感(0 不幸← →幸福10)",
family = "serif",
pch = "●",
col = "#7CAE0050")
)
マーカーを塗り潰しにした上でcolorに透過度を指定して,度数が多いところ程濃くなる様に工夫している。
with(d01,
plot(strata10, happy,
bty = "n",
las = 1,
main = "階層帰属意識と幸福感",
sub = sprintf("(平均:階層帰属意識 %.1f,幸福度 %.1f)",
mean(d01$strata10, na.rm = T),
mean(d01$happy, na.rm = T)),
xlab = "10段階階層帰属意識(1 下← →上 10)",
ylab = "幸福感(0 不幸← →幸福10)",
family = "serif",
pch = "●",
col = "#7CAE0050")
)
abline(lm(happy ~ strata10, d01),
lty = "dotted",
lwd = 3,
col = "#F8766Ddd")
text(mean(d01$strata10, na.rm = T),
mean(d01$happy, na.rm = T),
"×",
col = "blue",
cex = 1.5, # textのsize
font = 2) # bold指定
5.2 ggplotでの散布図
ggplot(d01, aes(x = strata10, y = happy)) +
geom_point()
回帰直線は,geom_abline( )で書き込むよりも,geom_smooth(method = “lm”)で書き込む方が楽。defaultでは95%信頼区間を描くが,不要であれば se = F とすれば良い。
ggplot(d01, aes(x = strata10, y = happy)) +
geom_point(alpha = .4,
color = "#7CAE00") +
scale_x_continuous(breaks = 1:10) +
scale_y_continuous(breaks = 0:10) +
labs(title = "階層帰属意識の分布と幸福度",
subtitle = sprintf("(平均:階層帰属意識 %.1f,幸福度 %.1f)",
mean(d01$strata10, na.rm = T),
mean(d01$happy, na.rm = T)),
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "10段階階層帰属意識(1 下← →上 10)",
y = "幸福感(0 不幸← →幸福10)",
tag = "図1") +
theme_classic() +
geom_smooth(method = "lm", se = F, linetype = "dotted")
但しこれだと,標準関数ではなくggplotを使用しているメリットは余り無い。
標準関数では簡単に出来ない事をやってみる。
前の例とのスクリプトの違いは非常に僅かである。
ggplot(d01, aes(x = strata10, y = happy, color = SEX)) +
geom_point(alpha = .4) +
scale_x_continuous(breaks = 1:10) +
scale_y_continuous(breaks = 0:10) +
labs(title = "階層帰属意識の分布と幸福度",
subtitle = sprintf("(平均:階層帰属意識 %.1f,幸福度 %.1f)",
mean(d01$strata10, na.rm = T),
mean(d01$happy, na.rm = T)),
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "10段階階層帰属意識(1 下← →上 10)",
y = "幸福感(0 不幸← →幸福10)",
color = "",
tag = "図1") +
theme_classic() +
geom_smooth(method = "lm", se = F, linetype = "dotted") +
theme(legend.position = c(.9, .2))
6 箱ひげ図
6.1 標準関数での箱ひげ図
1変数の箱ひげ図では余り利点が活かされない。
with(d01,
boxplot(happy)
)
グループ間比較には有効。
序に幾つかオプションを付けている。
family や bty はboxplot( )では其の儘指定しても効かないので,par( )に入れて指定する。
with(d01,
boxplot(happy ~ JOB,
varwidth = T,
main = "幸福感の職業間比較",
sub = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
xlab = "従業上の地位",
ylab = "幸福感(0 不幸← →幸福10)",
col = c("#99003360", "#99CC0060",
"#9999FF60", "#6699FF60"),
border = c("#990033", "#99CC00",
"#9999FF", "#6699FF"),
las = 1,
par(family = "serif", bty = "n")
) )
6.2 ggplotでの箱ひげ図
敢えて多くのオプションを付けて例示としている。
ggplot(d01[!is.na(d01$JOB), ],
aes(x = JOB, y = strata10, color = JOB, fill = JOB)) +
geom_boxplot(varwidth = T, alpha = .3) +
scale_y_continuous(breaks = 1:10) +
labs(title = "階層帰属意識の箱ひげ図",
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "従業上の地位",
y = "階層帰属意識(下← →上)",
color = "",
fill = "",
tag = "図A") +
theme_minimal() +
theme(legend.position = "none")
ggplot(d01[!is.na(d01$JOB), ],
aes(x = JOB, y = strata10, color = JOB, fill = JOB)) +
geom_boxplot(varwidth = T, alpha = .3) +
scale_y_continuous(breaks = 1:10) +
stat_summary(fun.y = "mean", geom = "point", color = "red") +
labs(title = "階層帰属意識の箱ひげ図",
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "従業上の地位",
y = "階層帰属意識(下← →上)",
color = "",
fill = "",
tag = "図A") +
theme_minimal() +
theme(legend.position = "none") +
facet_wrap(~ SEX)
ggplot(d01[!is.na(d01$JOB) & !is.na(d01$UNIV), ],
aes(x = JOB, y = strata10, color = JOB, fill = JOB)) +
geom_boxplot(varwidth = T, alpha = .3) +
geom_jitter(width = .2, height = .05, alpha = .2) +
scale_y_continuous(breaks = 1:10) +
stat_summary(fun.y = "mean", geom = "point", color = "red") +
labs(title = "階層帰属意識の箱ひげ図",
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "従業上の地位",
y = "階層帰属意識(下← →上)",
color = "",
fill = "",
tag = "図A") +
theme_minimal() +
theme(legend.position = "none") +
facet_grid(SEX ~ UNIV)
6.3 ggplotでのヴァイオリン・プロット
ggplot(d01[!is.na(d01$JOB), ],
aes(x = JOB, y = strata10, color = JOB, fill = JOB)) +
geom_boxplot(width = .2, alpha = .3) +
geom_violin(alpha = 0) +
stat_summary(fun.y = "mean", geom = "point", color = "red") +
scale_y_continuous(breaks = 1:10) +
labs(title = "階層帰属意識の箱ひげ図とヴァイオリン図",
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "従業上の地位",
y = "階層帰属意識(下← →上)",
color = "",
fill = "",
tag = "図A") +
theme_minimal() +
theme(legend.position = "none") +
facet_grid(~SEX)
7 モザイクプロット
7.1 標準関数でのモザイクプロット
分割表を其の儘可視化する。
基本的なオプションを付けて示す。
x軸ラベルは冗長なので情報表示に活用している。
with(d01,
mosaicplot(SEX ~ EDU2,
off = 3,
col = c("#99003360", "#99CC0060", "#9999FF60"),
border = "#777777",
main = "男女別の最終学歴",
sub = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
xlab = sprintf("χ2(%d)= %.1f, Cramer's V= %.3f",
$parameter,
chi01$statistic, V),
chi01ylab = "最終学歴",
las = 1,
par(family = "serif")
) )
7.2 ggmosaicでのモザイクプロット
ggplotでモザイクプロットを描くには更に追加のパッケイジをインストールする必要があるので必ずしも推奨しない。
# install.packages("ggmosaic")
library(ggmosaic)
ggplot(d01[complete.cases(d01$JOB, d01$EDU2), ]) +
geom_mosaic(aes(x = product(JOB, EDU2), fill = JOB), na.rm = T) +
labs(title = '性別・学歴別の従業上の地位',
subtitle = ,
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "",
y = "") +
theme_mosaic() +
theme(legend.position = "none",
text = element_text(family = "serif")) +
facet_wrap(~ SEX, scale = "free")
8 交互作用プロット
8.1 標準関数での交互作用プロット
X軸はカテゴリカルに扱われており,厳密にはやや問題がある。
x軸は等間隔尺度か,単なる順序尺度の方が適しているか。
with(d01,
interaction.plot(edu, SEX, income,
fun = function(x) mean(x, na.rm = T),
ylim = c(0,800),
bty = "l",
lty = c("dotted", "solid"),
main = "性・教育年数別の世帯年収平均",
sub = "※ x軸のメモリが等間隔で正しくない",
xlab = "本人教育年数(年)",
ylab = "平均世帯年収(万円)",
trace.label = "性別",
las = 1,
col = c("#008b8b", "#663333"),
family = "serif",
fixed = T
) )
8.2 ggplotでの交互作用プロット
x-yグラフがzによって2本になっているのが交互作用プロットである。
つまり3変数の関連をグラフにしたものであり,或意味では実はggplotでの交互作用の例は既に上に出てきている。
ここでは標準関数と同様で,より正確なグラフをggplotで描画する。
ggplot(d01,
aes(x = edu, y = income, color = SEX)) +
stat_summary(fun = "mean", geom = "line") +
labs(title = "教育年数と本人収入(男女別)",
caption = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
x = "教育年数(年)",
y = "個人年収平均(万円)",
color = "",
fill = "",
tag = "Fig. 1") +
theme_minimal() +
theme(legend.position = c(.9, .2))
これを別のグラフで書くと以下の様にもなる。
<-
gg01 ggplot(d01,
aes(x = edu, y = income, color = SEX, fill = SEX)) +
geom_jitter(width = .1, height = .05, alpha = .4) +
geom_smooth(method = "loess") +
labs(title = "教育年数と本人収入(男女別)",
subtitle = "東京・千葉・埼玉・神奈川 30-59歳男女(2014年)",
caption = "",
x = "教育年数(年)",
y = "個人年収(万円)",
color = "",
fill = "",
tag = "Fig. 1") +
theme_minimal() +
theme(legend.position = c(.2, .8))
gg01+ coord_cartesian(ylim = c(0, 1000)) +
gg01 labs(caption = "縦軸は2500まで存在するが描画範囲を1000までに限定した。",
tag = "Fig. 2")
Footnotes
データと説明書PDFは『入門・社会統計学』旧版サポートウェブのフロントページで提供している。↩︎
na.translate = F↩︎
!is.na(d01$STRATA5)の行(ケース)だけに限定している。↩︎