Mukku John Blog

取り組んでいること を つらつら と

ggplot2を使って、散布図を作る-5

R グラフィックス クックブック 14回目

ggplot2パッケージを利用して、散布図を作成していきます。
散布図上に、注釈のテキストやラグを表示します。

使うデータ

今までも使ってきた、こちらのデータを使います。

> str(heightweight)
'data.frame':	236 obs. of  5 variables:
 $ sex     : Factor w/ 2 levels "f","m": 1 1 1 1 1 1 1 1 1 1 ...
 $ ageYear : num  11.9 12.9 12.8 13.4 15.9 ...
 $ ageMonth: int  143 155 153 161 191 171 185 142 160 140 ...
 $ heightIn: num  56.3 62.3 63.3 59 62.5 62.5 59 56.5 62 53.8 ...
 $ weightLb: num  85 105 108 92 112 ...

テキストの表示

グラフ上に、テキストを表示するには、annotate()を使います。

注釈テキストの表示

グラフは前の記事で作成したのを、使いまわしています。

#表示するテキストの指定と、テキストの位置をx軸/y軸で指定する
グラフ + annotate("text",label="x軸16で、y軸が52.5です。",x=16,y=52.5)

f:id:MukkuJohn:20160902214735p:plain

Rの数式表現を使う場合は、parse=TRUEを指定します。

グラフ + annotate("text",label="r^2==0.42",parse=TRUE,x=16,y=52.5)

f:id:MukkuJohn:20160902215147p:plain

このテキストですが、グラフの注釈を添えるのが良いでしょうね。
関係ないテキスト表示しても???だし。
グラフの注釈ですが、表現しているモデルオブジェクト内に情報があります。

> summary(model)

Call:
lm(formula = heightIn ~ ageYear, data = heightweight)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.3517 -1.9006  0.1378  1.9071  8.3371 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  37.4356     1.8281   20.48   <2e-16 ***
ageYear       1.7483     0.1329   13.15   <2e-16 ***
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.989 on 234 degrees of freedom
Multiple R-squared:  0.4249,	Adjusted R-squared:  0.4225 
F-statistic: 172.9 on 1 and 234 DF,  p-value: < 2.2e-16

注釈を添える場合は、↑のモデルの情報から抜粋するのですが、
いちいち、モデルの情報を確認してから、テキストを固定で追加せずに、
動的に、テキストを組み立てる方法があります。


まず、summary()で確認した情報ですが、
この様に、$表記で、その情報のみアクセスできます。

> summary(model)$r.squared
[1] 0.4249409

そのほか係数部分は、coef()を使ってアクセスできます。

> coef(model)
(Intercept)     ageYear 
  37.435574    1.748253 

> coef(model)[1]
(Intercept) 
   37.43557 


上記を駆使して、こんな感じで、数式を組み立てられます。

モデルの数式 <-as.character(as.expression(
  substitute(italic(y)==a+b*italic(x)*","~~italic(r)^2~"="~r2,
             list(a=format(coef(model)[1],digits=3),
                  b=format(coef(model)[2],digits=3),
                  r2=format(summary(model)$r.squared,digits = 2)
                ))))

> モデルの数式
[1] "italic(y) == \"37.4\" + \"1.75\" * italic(x) * \",\" ~ ~italic(r)^2 ~ \"=\" ~ \"0.42\""

> parse(text=モデルの数式)
expression(italic(y) == "37.4" + "1.75" * italic(x) * "," ~ ~italic(r)^2 ~ "=" ~ "0.42")

あとは、モデルの数式オブジェクトを使って、注釈を添えるだけです。

#x位置とy位置をの指定にInfを使いました
#テキストが見切れない様に、hjustとvjustで位置を調整しています。
グラフ + annotate("text",label=モデルの数式,parse=TRUE,
               x=Inf,y=-Inf,hjust=1.1,vjust=-.5)

f:id:MukkuJohn:20160902221304p:plain

データポイントのラベル表示

基本的には、注釈テキストと同様に、annotate()を使います。
対象のデータを変えます。(オブジェクトの日本語やめました。multi byte parse error...)

#healthexpとinfmortalityを使います
#healthexp:健康のための出費/infmortality:幼児死亡率

> str(healthData)
'data.frame':	27 obs. of  7 variables:
 $ Name        : Factor w/ 216 levels "Afghanistan",..: 5 11 12 19 34 53 66 67 72 75 ...
 $ Code        : Factor w/ 216 levels "ABW","AFG","AGO",..: 5 11 12 15 33 54 63 65 51 77 ...
 $ Year        : int  2009 2009 2009 2009 2009 2009 2009 2009 2009 2009 ...
 $ GDP         : num  NA 42131 45555 43640 39599 ...
 $ laborrate   : num  NA 65.2 60.4 53.5 67.8 65.4 60.9 56.1 59.8 53.7 ...
 $ healthexp   : num  3090 3867 5037 5104 4380 ...
 $ infmortality: num  3.1 4.2 3.6 3.6 5.2 3.4 2.5 3.5 3.5 3.5 ...

グラフを作ります。

>scatterPlot <- ggplot(healthData,aes(healthexp,y=infmortality)) + 
  geom_point()

>scatterPlot

f:id:MukkuJohn:20160902222124p:plain

ラベルを付けるためには、データポイントの位置を指定します。

#x軸の位置
> healthData$healthexp[healthData$Name == "Japan"]
[1] 3321.466

#y軸の位置
> healthData$infmortality[healthData$Name == "Japan"]
[1] 2.4

ラベルを表示します。

#データポイントの位置は、y=2.4だけでど、ラベルをその位置で表示すると
#データポイントとかぶるので、 y軸に対して +0.2しておく
scatterPlot + 
  annotate("text", x=3321.466, y=2.4 + 0.2, label="Japan") 

f:id:MukkuJohn:20160902224317p:plain
メンドクサイですが、こんな感じです。

全てのデータポイントに対して、行う場合は、geom_text()を使います。

#位置の調整と、サイズの調整をしています。
#サイズはデフォルト5です
scatterPlot + 
  geom_text(aes(y=infmortality + .1, label=Name), size = 4, vjust=0)

f:id:MukkuJohn:20160902224807p:plain

特定のデータポイントだけ表示させたい場合は、そのためのデータを作成します。

#とりあえず違う列を用意する
healthData$Name1 <- healthData$Name

#表示させたい条件を作る
idx <- healthData$Name1 %in% c("Canada","Ireland","United Kingdom",
                         "New Zealand","Iceland","Japan",
                         "Luxembourg","Netherlands","Switzerland")

#表示させたい条件以外は、欠損データにする
healthData$Name1[!idx] <- NA

作ったデータをgeom_text()label引数に指定します。

ggplot(healthData, aes(x=healthexp,y=infmortality)) + 
  geom_point() +
  geom_text(aes(x=healthexp+100,label=Name1),size=4,hjust=0) +
  xlim(2000,10000)

f:id:MukkuJohn:20160902225225p:plain

ラグの表示

ラグとは、このグラフの縁の線です。
f:id:MukkuJohn:20160902225457p:plain
geom_rug()で表示させます。

#上のグラフのコードです
ggplot(heightweight,aes(x=ageYear,y=heightIn)) + 
  geom_point() + 
  geom_rug()


このラグ、1次元の散布図と捉えることができます。
上のグラフは分布が分かりづらいですが、こちらは分かりやすいです。
R: Old Faithful Geyser Data

ggplot(faithful,aes(x=eruptions,y=waiting)) +
  geom_point() +
  geom_rug(position="jitter",size=.2)

f:id:MukkuJohn:20160902225818p:plain


次回は、データポイントがサイズを持つ散布図(バルーンプロット)や
行列で表示された散布図を作ります。