R上でデータの可視化(グラフ等を描く)作業を行うためのパッケージとして,ggplot2が広く利用されている.

正直に言えば,可視化作業は,データ分析の中で最も面倒な作業の一つである.このため,データを分析自体はRで行うものの,可視化作業はRで得られた結果をExcel等にコピーして,Excel上で行うのでも構わないと言えば構わない.ただ,結果をExcelのコピーする際にミスをしてしまうことも有りるし,同じ分析方法であっても,対象のデータを変わった場合には,当然ながらまた手作業でイチからグラフを作り直すことになる.さらに,複数人で作業をしている場合などは,それぞれのグラフのデザインが異なって,見栄えが悪くなるといことも起こり得る.

ggplot2を用いれば,Rの出力結果をそのままグラフ化できるので,「コピーの際の手違い」というものは起こり得ないし,データが変わった場合にも,コードを少し変えるだけでグラフを作り直すことができる.さらに,ggplot2を用いることで統一されたデザインポリシーの下でグラフを描くこともできる.

この章では,ggplot2の基本的な使い方を説明する.

1 ggplot2のインストール

ggplot2は美しい描画をしてくれる様々な関数を提供する外部パッケージである.利用するためには,データハンドリングで使ったtidyverseを読み込む.データハンドリングの時に一度インストールをしているので,今度はスクリプトの冒頭にlibrary(tidyvers)と書き入れるだけでよい.

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

ggplot2自体は「ggplot2」という名前のパッケージであり,インストールするパッケージも本来であれば「ggplot2」パッケージで良いのだが,「tidyverse」パッケージではggplot2を含め様々な便利なパッケージがまとめられている.後々それらのパッケージも利用していきたいので,ここではtidyverseパッケージを利用する.

2 ggplot2をつかった描画の基本的な流れ

Step1:データを与えて描画キャンバスを作る

Step2:与えたデータに対して各種の描画命令を与える

Step3:必要ならば凡例や軸の書式の設定をする

Step4:plot()関数を実行する.

3 データの準備

ggplotで処理するデータはロング形式のデータである必要がある. ここでは,前回と同様にirisデータを使うことにする.irisデータは最初からロング形式であるため,そのまま使うことができる. 以下ではirisデータを読み込んで,変数名(列名)を日本語に変更した後,head()関数を用いてデータの冒頭6行分を表示させている.

data_iris <- iris
colnames(data_iris) <-  c("がく長","がく幅","花びら長","花びら幅","種類")
head(data_iris)
##   がく長 がく幅 花びら長 花びら幅   種類
## 1    5.1    3.5      1.4      0.2 setosa
## 2    4.9    3.0      1.4      0.2 setosa
## 3    4.7    3.2      1.3      0.2 setosa
## 4    4.6    3.1      1.5      0.2 setosa
## 5    5.0    3.6      1.4      0.2 setosa
## 6    5.4    3.9      1.7      0.4 setosa

4 キャンバスの作成

キャンバスの作成にはggplot()関数を用いる.引数にはデータを与える.

g <- ggplot(data_iris)

これでキャンバスのオブジェクトがgという名前で格納された.このgに対して,色々な描画関数を与えていき,最後にgplot()関数で実際に描画させる,というのが基本的な描画のフローとなる.

ちなみに現時点でplot()を実行すると以下のようになる.

plot(g)

このとおり,まだ中身がなにもないので描画エリアだけの描画となる.

5 描画関数の実行

5.1 箱ひげ図

まずはがく長の箱ひげ図を書かせることにしよう.

5.1.1 単純な箱ひげ図

箱ひげ図を書かせる命令はgeom_boxplot()関数となる.この関数の第1引数にaes()関数をあたえる.aes()関数ではさらにx軸,y軸のデータを設定する.data_irisに含まれている「がく長」の全体のデータを箱ひげ図にしてみよう.データ全体なので,x軸には文字列として”全体”としておく.

g <- ggplot(data_iris) + geom_boxplot(aes(x="全体", y=がく長))
plot(g)

y とxを入れ替えると以下の通りとなる.

g <- ggplot(data_iris) + geom_boxplot(aes(x=がく長, y="全体"))
plot(g)

5.1.2 種類ごとの箱ひげ図

上記はあくまでがく長全体を一まとめのデータとして扱ったが,例えば,x軸を種類に設定して,種類ごとの箱ひげ図を書かせたいといった場合には以下の通りにする.先ほどと違い種類にはダブルコーテーションはつかない.これは種類はあくまでdata_irisに含まれる変数名であり,単なる文字列であった"全体"というのと根本的に異なるものであるためである.

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長))
plot(g)

このように箱ひげ図が種類ごとに描かれる.

5.1.2.1 種類ごとに塗り分ける

箱ひげ図に色を塗りつぶしたい場合には,aes()fill(塗りつぶし)の設定を与える.塗分けは箱ひげ図の場合にはグループ単位で行いたいであろう.そういう場合には,グループ分けに使っている変数,すなわち種類を与えると良い.

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長, fill=種類))
plot(g)

塗りつぶしではなく,枠のみに色を付けたい場合には,fillの代わりに,colorの設定を与える.

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長, color=種類))
plot(g)

fillとcolorの両方を設定することもできるが,それをすると,枠線と塗りつぶしの色が同じになってしまい,中央値が見えなくなるので,いずれか一方にするべきである.

5.1.2.2 箱の幅を変える

geom_boxplot()の第2引数(aes()関数の外の引数)としてwidthを与える.デフォルトは0.75に設定されてる.

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長, fill=種類),width=0.3 )
plot(g)

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長, fill=種類),width=1.0 )
plot(g)

g <- ggplot(data_iris) + geom_boxplot(aes(x=種類, y=がく長, fill=種類),width=0.75)
plot(g)

5.1.3 複数の変数の箱ひげ図

今までは「がく長」のみを描画してきたが,「がく幅」や「花びら長」なども同時に描画させたい場合には,以下のようにgeom_boxplotを各変数に対して設ける.x=で記載されるものはあくまでラベルとなるため,ダブルコーテーション(““)が必要となる.

g <- ggplot(data_iris) + 
  geom_boxplot(aes(x="がく長",y=がく長))+
  geom_boxplot(aes(x="がく幅", y=がく幅))+
  geom_boxplot(aes(x="花びら長", y=花びら長))

plot(g)

なお,このようにした場合には,種類ごとに分けることはできなくなる(x軸が変数に対応する形になるので,種類に対応させる軸がなくなる).

5.1.3.1 変数ごとに塗り分ける

塗色をしたい場合には,fillcolorの設定を与える.以下ではfillを設定している.この例のように,fillに変数名を設定すると,その変数名に従って色分けされる.

g <- ggplot(data_iris) + 
  geom_boxplot(aes(x="がく長",y=がく長, fill="がく長"))+
  geom_boxplot(aes(x="がく幅", y=がく幅, fill="がく幅"))+
  geom_boxplot(aes(x="花びら長", y=花びら長, fill="花びら幅"))

plot(g)

colorを設定した場合.

g <- ggplot(data_iris) + 
  geom_boxplot(aes(x="がく長",y=がく長, color="がく長"))+
  geom_boxplot(aes(x="がく幅", y=がく幅, color="がく幅"))+
  geom_boxplot(aes(x="花びら長", y=花びら長, color="花びら幅"))

plot(g)

このデータは,ある地域Aとある地域Bの高校生をランダムに500人ずつ抽出し,それぞれの大学入試共通テストの数学IA,数学IIB,国語をデータ化したものである.このデータを使って,以下の問に答えよ

  1. このデータをhead()関数とsummary()関数を使って確認せよ.なお,地域については要因型に変換しておくこと.
  2. 数学IAについて地域別の箱ひげ図を作成せよ.
  3. 各科目の箱ひげ図を描画せよ.

5.2 点プロット

5.2.1 基本の点プロット

基本はgeom_point()である.引数としてaes()を使ってx,yを設定する.以下は,がく長全体のデータをプロットしたものである.

g <- ggplot(data_iris)+geom_point(aes(x="全体", y=がく長))
plot(g)

つづいて,種類ごとのがく長をプロットした例である.

g <- ggplot(data_iris)+geom_point(aes(x=種類, y=がく長))
plot(g)

全体にしても種類ごとにしても,がく長は0.1刻みで測定されているため,値が同じものが含まれている.上記の設定では,それらは全部重なってしまうため,上記のようなプロットとなる.

5.2.2 点をばらつかせる(Jitter)

geom_point()だと上記のように同じ値のものが全部重なって1つの点として表記されるため,データ全体がどのように分布しているのかが把握できなくなる.そこで,同じ値のものを水平方向にランダムにバラつかせて描画させるために, geom_jitter()を使う.引数はgeom_point()と同じである.

g <- ggplot(data_iris)+geom_jitter(aes(x=種類, y=がく長))
plot(g)

水平方向にランダムにばらついたことによって,同じ値を取っているものがどれだけあるかがある程度視覚的に把握できるようになる.

もう一度描画させると,先ほどと違うばらつき方になる.

g <- ggplot(data_iris)+geom_jitter(aes(x=種類, y=がく長))
plot(g)

Jitterではなく度数分布にする

先の例では点をプロットするときに横方向にランダム化させるjitter表示にしていたが,度数分布にすることもできる. 度数分布の場合には,geom_jitter()の代わりにgeom_dotplot()関数を用いる.引数がやや多いので以下に表で示す.

引数名 内容
aes(x=, y=) x軸,y軸の設定
binaxis どちらの軸の変数についての度数分布にするのか
dotsize プロットする点のサイズ
stackdir どの方向にプロットしていくか.Up(右向き), down(左向き), center(中心ぞろえ)のいずれか
binwidth 度数分布における区間幅の設定
position position_nudge()関数によって描画開始をそれぞれのグループのx軸の中心からどちら向き(正か負か)にどれだけ離すかの設定する.stackdirをcenterにした場合には中心がずれる

以下に,実際にいくつか例示してみる.なお,1行のソースコードが長くなってきたので,見やすさのため+で改行しているほか,関数内でも引数単位で適宜改行を入れている.

g <- ggplot(data_iris)+
  geom_dotplot(aes(x=種類, y=がく長), binaxis = "y", dotsize = 1.0, stackdir = "down",
               binwidth = 0.1, position = position_nudge(-0.025))
plot(g)

g <- ggplot(data_iris)+
  geom_dotplot(aes(x=種類, y=がく長), binaxis = "y", dotsize = 0.50, stackdir = "up",
               binwidth = 0.1, position = position_nudge(0.025))
plot(g)

g <- ggplot(data_iris)+
  geom_dotplot(aes(x=種類, y=がく長), binaxis = "y", dotsize = 0.3, stackdir = "center",
               binwidth = 0.3, position = position_nudge(0.225))
plot(g)

以下はbinaxisをxに設定しているためエラーとなる(xはグループ分け変数であり,概念上度数分布というものが存在しないので).

g <- ggplot(data_iris)+
  geom_dotplot(aes(x=種類, y=がく長), binaxis = "x", dotsize = 0.3, stackdir = "up",
               binwidth = 0.1, position = position_nudge(0.025))
plot(g)
## Warning: The following aesthetics were dropped during statistical transformation: y.
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
##   the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
##   variable into a factor?
## Error in `geom_dotplot()`:
## ! Problem while setting up geom.
## ℹ Error occurred in the 1st layer.
## Caused by error in `compute_geom_1()`:
## ! `geom_dotplot()` requires the following missing aesthetics: y.

5.2.3 色やプロット範囲の幅を変える

箱ひげ図の時と同様に,色や幅を変えることができる.色についてはfill(塗りつぶし)ではなくcolorを設定したり,Widthを設定したりして,色や幅を変えることができる.

g <- ggplot(data_iris)+geom_jitter(aes(x=種類, y=がく長, color=種類))
plot(g)

g <- ggplot(data_iris)+geom_jitter(aes(x=種類, y=がく長, color=種類), width = 0.3)
plot(g)

5.2.4 箱ひげ図との重ね合わせ

点のプロットと箱ひげ図を重ねることもできる.以下のようにgeom_boxplot()geom_dotplot()geom_jitter()+でつなげればよい.

g<- ggplot(data_iris)+
  geom_boxplot(aes(x=種類,y=がく長))+
  geom_jitter(aes(x=種類, y=がく長, color=種類))
plot(g)

g<- ggplot(data_iris)+
  geom_boxplot(aes(x=種類,y=がく長), width=0.5)+
  geom_dotplot(aes(x=種類, y=がく長, color=種類, fill=種類), binaxis = "y", 
               dotsize = 0.75, stackdir = "down",binwidth = 0.1, 
               position = position_nudge(-0.025))
plot(g)

aes()(エステティック)関数の設定項目はx,y軸とfill(塗りつぶし), color(線や点の色設定)が出てきているが,それ以外に以下のようなものがある.

項目 内容
x, y x軸に設定する変数,y軸に設定する変数
color 点や線の色
fill 面の色
alpha 不透明度 (0が透明,1が不透明)
size 点や文字の大きさ,線の太さ
shape 点の形
linetype 線の種類
group 反復試行の折れ線グラフなど,色や形はそのままで切り分けたいときに.
xmin, xmax, ymin, ymax, xend, yend ものによってつかう.

極めて多いエラーとして,各geom()関数を実行していくときに,前の行の末尾に+を付け忘れたり,最後の行の末尾に+をつけたりしてしまうことがよくある. もし,エラーが出てグラフ描画ができなかった場合には,これらのミスをしていないかを確認してみてほしい.

先ほど読み込んだ大学入試共通テストの得点データ(数学IA,数学IIB,国語)を使って以下の問に答えよ.

  1. 各科目の箱ひげ図に個々の得点のjitterプロットを重ねて描画せよ.箱ひげ図は色付けはせず,Jitterプロットは色付けすること.
  2. 数学IAについて地域ごとの箱ひげ図に,地域ごとの個々の得点のjtterプロット重ねて描画せよ.箱ひげ図は色付けはせず,Jitterプロットは色付けすること.

5.3 棒グラフとエラーバー

平均を棒グラフとして,さらに標準偏差や信頼区間をエラーバーとして描く,というケースは非常に多い.そこで以下ではそういう棒グラフの作成方法を説明する.

5.3.1 棒グラフの基本

流れとしては平均と標準偏差の求め,それを元のデータとは別のデータフレームに格納し,そのデータフレームを用いて描画する,という流れとなる.

用いるggplot2の関数はgeom_bar()geom_errorbar()である.

geom_bar()は棒グラフを描く関数である.第1引数としてaes()関数を与え,x軸とy軸を設定する.第2引数にはstat="identity"を与える.これは「与えたデータをそのまま使う」という意味である.第3引数にはwidthを与える.これは棒の幅を設定する.ただ,第3引数は省略することもできる.

geom_errorbar()はエラーバーを描く関数である.第1引数としてaes()関数を与え,x軸,y軸,ymin,ymaxを設定する.x軸,y軸はgeom_bar()に与えたものと同じもの与える.yminはエラーバーの下限,ymaxはエラーバーの上限を示す.一般的には平均\(\pm\)標準偏差もしくは信頼区間の上限・下限が与えられる.widthはエラーバーの幅を設定する.widthを省略すると,上限・下限を示す水平方向の線分が描かれなくなる.

#データの準備
平均 <- mean(data_iris$がく長)
標準偏差 <- sd(data_iris$がく長)

d <- data.frame( # それぞれ1つずつの値しか格納されていないが,あくまでデータフレームである
  平均 = 平均,
  標準偏差 = 標準偏差
)

g<-ggplot(d)+
  geom_bar(aes(x="全体",y=平均), stat="identity",width = 0.5)+
  geom_errorbar(aes(x="全体",y=平均,ymin=平均-標準偏差, ymax=平均+標準偏差),width=0.15)
plot(g)

5.3.2 種類ごとに分けた棒グラフにしたい

aggregate()関数グループごとのデータを用意した上で,以下のようにする.

#データの準備
d.mean <- aggregate(がく長~種類,data_iris, mean)
d.sd <- aggregate(がく長~種類,data_iris, sd)
d.mean
##         種類 がく長
## 1     setosa  5.006
## 2 versicolor  5.936
## 3  virginica  6.588
d.sd
##         種類    がく長
## 1     setosa 0.3524897
## 2 versicolor 0.5161711
## 3  virginica 0.6358796
d2 <- data.frame(
  種類 = d.mean$種類,
  平均 = d.mean$がく長,
  標準偏差= d.sd$がく長
)
print(d2) 
##         種類  平均  標準偏差
## 1     setosa 5.006 0.3524897
## 2 versicolor 5.936 0.5161711
## 3  virginica 6.588 0.6358796
 g <- ggplot(d2)+
  geom_bar(aes(x=種類,y=平均,fill=種類),stat="identity")+
  geom_errorbar(aes(x=種類,y=平均,ymin=平均-標準偏差, ymax=平均+標準偏差),width=0.15)
plot(g)

さらに,平均値自体を棒グラフに重ねて記述したい場合には以下のようgeom_text()を用いるる.vjustは,テキストの位置を調整するためのパラメータで,数値が大きいほど下に移動する.負の値にした場合は棒グラフよりも上の表記される.

g <- ggplot(d2)+
  geom_bar(aes(x=種類,y=平均,fill=種類),stat="identity")+
  geom_errorbar(aes(x=種類,y=平均,ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.15))+
  geom_text(aes(x=種類,y=平均,label=round(平均,1)),vjust=5)
plot(g)

今まで,キャンバスを作った際にデータフレームを与え,その後,描画をする際にxとyを指摘してきたが,キャンバスを作るときにxとyも指定することができる.そうすると,描画をするときに,いちいちx,yを指定しなくても良くなる.以下に例を示す.

g <- ggplot(d2)+
  geom_bar(aes(x=種類,y=平均,fill=種類),stat="identity")+
  geom_errorbar(aes(x=種類,y=平均,ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  geom_text(aes(x=種類,y=平均,label=round(平均,1)),vjust=5)
plot(g)

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  geom_text(aes(label=round(平均,1)),vjust=5)
plot(g)

データそのものを使って描く方法

データそのものを使って描く場合には以下のようにする. ポイントは以下の通りである.

  • geom_barstatsummaryに設定し,fun.dataに平均と標準偏差を求める関数であるmean_sdlに設定するか,funに平均を求める関数であるmeanを設定することである.
  • geom_errorbarstatを同じくsummaryに設定し,fun.dataに平均と標準偏差を求める関数であるmean_sdlに設定する.さらにfun.argsにはmean_sdl関数の引数であるmult1に設定することで,1倍の標準偏差を算出させる.
    • mean_sdlHmiscパッケージに含まれているsmean.sdlという関数を用いて平均と標準偏差を算出してくれる関数である.このsmean_sdl関数では,第2引数としてmultという引数があり,これを1に指定すると1*標準偏差が,2とすると2*標準偏差が算出されるようになる.もし引数を設定しなかった場合には,デフォルト値をとして2に自動で設定される.
    • mean_sdlを実施するためにはHmiscパッケージをインストールしておく必要がある.
  • geom_textでlabelを与える際にafter_stat()関数を使って,statで求めた値を使うように設定した上で,statfunをそれぞれsummarymeanに設定する.
g <- ggplot(data_iris, aes(x=種類,y=がく長,fill=種類))+
  geom_bar(stat = "summary", fun.data = "mean_sdl")+ # geom_bar(stat = "summary", fun = "mean") でもよい
  geom_errorbar(stat = "summary", fun.data = "mean_sdl", fun.args = list(mult = 1), width=0.15)+
  geom_text(aes(label = round(after_stat(y), 2)), stat = "summary", fun = "mean", vjust = -0.5)
plot(g)

なお,上記はエラーバーとして標準偏差を表示させる方法であるが,エラーバーとして標準誤差を使う場合には,もう少しシンプルに書く事が出来る.

g <- ggplot(data_iris, aes(x=種類,y=がく長,fill=種類))+
  geom_bar(stat = "summary",fun.data = mean_se)+
  geom_errorbar(stat = "summary", fun.data = "mean_se", width=0.15)+
  geom_text(aes(label = round(after_stat(y), 2)), stat = "summary", fun = "mean", vjust = -0.5)
plot(g)

geom_bar()に対いて警告が表示されるが,それは"summary"に指定しているのに明示的にfunを指定していないため,デフォルトである”mean_se”が適用されていた,ということを示しているだけであるので,気にする必要はない.もし表示を消したければ,fun="mean_se"を明示的に指定すればよい.

先ほど読み込んだ大学入試共通テストの得点データ(数学IA,数学IIB,国語)を使って以下の問に答えよ.

  1. 各科目について平均値と標準偏差を求め,それを棒グラフとエラーバーで描画せよ.エラーバーは標準偏差を用いること.また,それぞれの平均の値も棒グラフに重ねて記述すること.
  2. 数学IAについて,地域ごとの平均と標準偏差を求め,それを棒グラフとエラーバーで描画せよ.エラーバーは標準偏差を用いること. また,それぞれの平均の値も棒グラフに重ねて記述すること.

5.4 ヒストグラム

度数分布表(設定した区間幅のそれぞれに含まれるサンプル数を表にしたもの)をグラフ表示したものをヒストグラムと呼ぶ.ヒストグラムを作成するには geom_histgram()を使う

5.4.1 geom_histgram()を使う

geom_histgramを使う場合,区間幅はデフォルトではデータの範囲を30等分した値が自動的に設定されるが,binwidthを設定することによって任意の区間幅に設定することもできる.以下の例では,がく長の値を0.1単位で区切っている.

データを度数分布表やヒストグラムを描く際に,データを区間に分ける処理をbinningと呼ぶ.このため,geom_histgram()関数で区間幅の引数がbinwidthとなっている.

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長), binwidth = 0.1)
plot(g)

これだと区間の境界がわかりにくいので,境界を描かせるためには以下のようにする.

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)
plot(g)

5.4.2 種類ごとの色分け

種類ごとに分けて分布を作る場合は,aes()の中でfill`を設定する.

g <- ggplot(data_iris)+
  geom_bar(aes(x=がく長, fill=種類),stat="count")
plot(g)

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長, fill=種類),color="white", binwidth = 0.1)
plot(g)

なお,例えば,がく長が5.7は度数として8となっているが,これは3つの種類をすべて積み上げたものである.すなわち,setosaにおいてがく長5.8なのは2点,Versicolorでは5点,virginicaで1点となっている.

ただ,この場合,重なっている箇所については積み上げグラフになる.

5.4.3 種類別のヒストグラム作成

あくまで種類ごとにそれぞれ別々のヒストグラムにしたい,ということであれば,以下のように2つの方法が考えられる.

方法1 データを端からバラバラにして3つのグラフを別々に描く

この場合には,データをfilter()関数(->参考)を用いて種類ごとに分け,それぞれを描画する.ただし,この場合,coord_cartesian() 関数を使ってx軸の変域を設定しないと,3つのグラフのx軸,y軸の変域がバラバラになってしまう.なので,以下の例のように,coord_cartesian()を使ってx軸,y軸の変域を設定する.

なお,coord_cartesian()と類似の働きをするものとしては,xlim()ylim()があるが,xlim()ylim()はデータそのものからこれらで指定した範囲外のものを除外する(結果として表示も指定範囲に限定される)のに対して,coord_cartesian()はデータを除外しているわけではなく,単に表示する範囲を指定するだけである.

単に表示を変えたいだけならば,coord_cartesian()を使うべきである.

g <- ggplot(filter(data_iris,種類=="setosa"))+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)+
  #xlim(4,8)+ylim(0,30)
  coord_cartesian(xlim = c(4, 8), ylim=c(0,30))
plot(g)

g <- ggplot(filter(data_iris,種類=="versicolor"))+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)+
  #xlim(4,8)+ylim(0,30)
  coord_cartesian(xlim = c(4, 8), ylim=c(0,30))
plot(g)

g <- ggplot(filter(data_iris,種類=="virginica") )+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)+
  #xlim(4,8)+ylim(0,30)
  coord_cartesian(xlim = c(4, 8), ylim=c(0,30))
plot(g)

変数の内容を知るための関数としてstr()という関数がある.実際にこれをfilter()関数の結果に対してかけてみると,以下の通りとなる.

res<-filter(data_iris,種類=="setosa")
str(res)
## 'data.frame':    50 obs. of  5 variables:
##  $ がく長  : num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ がく幅  : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ 花びら長: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ 花びら幅: num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ 種類    : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

データ点数は50点とあり,確かにsetosaのみを取り出せているのがわかる.一方で「種類」列の情報としては,この列は要因型であり,3つの水準(setosa, versicolorだけが表示されているが・・・)で構成されていることが記載されていることがわかる.

方法2: 1つの絵の中で3つに分割して描く(facet_wrap()の利用)

facet_wrap()を利用することで1枚のキャンバスを分割して表示させることができる.

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)+
  facet_wrap(~種類)
plot(g)

デフォルトでは,横方向(列方向)に分割されていくが,nrow(行数)を設定することによって縦方向(行方向)にも分割させることができる.

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)+
  facet_wrap(~種類,nrow=2) 
plot(g)

5.4.4 複数の変数のヒストグラム

これまで「がく長」について種類別のヒストグラムを描く方法を説明したが,今度は,複数の変数(例えば,「がく長」と「がく幅」)のヒストグラムを描く方法を説明する.

方法は大きく2つある. 1つは,シンプルに変数ごとに別々のキャンバスを用意して描画する方法である. 以下はその例.

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく長),color="white", binwidth = 0.1)
plot(g)

g <- ggplot(data_iris)+
  geom_histogram(aes(x=がく幅),color="white", binwidth = 0.1)
plot(g)

もう1つは,facet_wrap()を使って1つのキャンバスに複数の変数のヒストグラムを描画する方法である. この場合は,ggplotに与えるデータをロング形式に変換する必要がある.すなわち,現状では,以下のような表になっているが

種類 がく長 がく幅 花びら長 花びら幅
setosa 5.1 3.5 1.4 0.2
setosa 4.9 3.0 1.4 0.2
setosa 4.7 3.2 1.3 0.2

以下のように変換する必要がある.

種類 変数
setosa がく長 5.1
setosa がく幅 3.5
setosa 花びら長 1.4
setosa 花びら幅 0.2
setosa がく長 4.9
setosa がく幅 3.0
setosa 花びら長 1.4
setosa 花びら幅 0.2
setosa がく長 4.7
setosa がく幅 3.2
setosa 花びら長 1.3
setosa 花びら幅 0.2

このように変換するためには,データハンドリングで紹介したpivot_longer()関数を使う.以下のようにする.

data_iris_long <- pivot_longer(data_iris, cols=c(がく長, がく幅, 花びら長, 花びら幅), names_to="変数", values_to="値")
head(data_iris_long)
## # A tibble: 6 × 3
##   種類   変数        値
##   <fct>  <chr>    <dbl>
## 1 setosa がく長     5.1
## 2 setosa がく幅     3.5
## 3 setosa 花びら長   1.4
## 4 setosa 花びら幅   0.2
## 5 setosa がく長     4.9
## 6 setosa がく幅     3

変換が出来たら,filter関数で描画させたい変数のみを抽出したうえで,geom_histgram()facet_wrap()を使って描画する.

g <- ggplot(filter(data_iris_long,変数=="がく長"|変数=="がく幅"))+
  geom_histogram(aes(x=値),color="white", binwidth = 0.1)+
  facet_wrap(~変数)
plot(g)

ただ,注意すべき点として,facet_wrap()を使う場合には,x軸の値域は全てのヒストグラムで同じものとなる.このため,上の図のように,明らかに個別の変数のデータとしてはデータが存在しない区間(がく長での4以下の区間や,がく幅での5以上区間)があっても,いずれかの変数でその区間にデータが存在すれば,すべての変数でその区間も含めた形のヒストグラムが描かれることになる.

ヒストグラムを比較することに意味があるなら,そのような表示でも問題はないが,比較するつもりはとくになく,それぞれの変数でヒストグラムを得たいだけならば,無理に1枚のキャンバスに描画しようとせずに,それぞれの変数ごとに別々に描画する方法をとる方がよいだろう.

先ほど読み込んだ大学入試共通テストの得点データ(数学IA,数学IIB,国語)を使って以下の問に答えよ.

  1. 数学IA,数学IIB,国語の3科目についてのヒストグラムをそれぞれ別のグラフとして描画せよ.区間幅は5点刻みとする.
  2. 数学IAについて地域別のヒストグラムを1枚のグラフとしてまとめたものをfacet_wrap()関数を用いて作成せよ.区間幅は5点刻みとする.

5.5 散布図

2つのデータの関係性を可視化するグラフの代表格は散布図である.散布図は点プロットで紹介したgeom_point()を用いて以下のようにして描く.

g <- ggplot(data_iris)+
  geom_point(aes(x=がく長, y=花びら長))
plot(g)

5.5.1 種類ごとに色分け

geom_point()aes()colorを与える.

g <- ggplot(data_iris)+
  geom_point(aes(x=がく長, y=花びら長, color=種類))
plot(g)

5.5.2 種類ごとにプロットの形を分ける

geom_point()aes()shapeを与える.

g <- ggplot(data_iris)+
  geom_point(aes(x=がく長, y=花びら長, color=種類, shape=種類))
plot(g)

分かりやすく,がく長と花びら長に関係性として,setosaにはほぼ関係性はないが,versicolorとvirginicaにはがく長が長くなると,花びら長も長くなる傾向にあることが分かった.

散布図は回帰分析を行う際の結果の可視化でも改めて触れることにする.

5.6 任意の位置に文字や図形を書き入れる

任意の場所に任意の文字や線,図形を書き入れる場合には,annotate()関数を使う.以下のように,geom_point()の後にannotate()を使って,任意の位置に任意の文字を書き入れることができる.以下に代表的な引数を示す.これら以外にも円を描いたり,矢印を描いたりできるので,興味がある人はChatGPTに聞いてみてほしい.

引数名 内容
第1引数 アノテーションの種類の指定.“text”(テキスト),“segment”(線分),“rect”(四角形)などがある
x,y アノテーションを書き入れるx,y座標
xend 線を引く場合の終点のx座標
yend 線を引く場合の終点のy座標
xmin, xmax, ymin, ymax 四角形を描く場合の座標
label 書き入れる文字列
color 文字の色,線の色
fill 四角形の塗りつぶしの色
size 文字の大きさ
angle 文字の角度
linewidth 線の幅
g <- ggplot(data_iris)+
  geom_point(aes(x=がく長, y=花びら長, color=種類, shape=種類))+
  annotate("text", x=5, y=2, label="ここに文字を書き入れる",color="orange",size=7, angle=39)+
  annotate("segment", x=4, y=2, xend=6, yend=3, linewidth=1.5)+
  annotate("rect", xmin=5, xmax=6, ymin=4, ymax=6,color="red",fill="blue")
plot(g)

先ほど読み込んだ大学入試共通テストの得点データ(数学IA,数学IIB,国語)を使って以下の問に答えよ.

  1. 数学IAをx軸,国語をy軸とする散布図を作成せよ.
  2. 上で作成した散布図について,地域別の色分けを行え.
  3. 上で作成した散布図に対して,annotationのsegmentを用いて,数学の平均点を示すY軸に平行な線分と国語の平均点を示すx軸に並行な線分を引け.
  4. 上で作成した線分の入った散布図に対して,線分をx軸,y軸と見立てて,annotationのtextを用いて,「第1象限」から「第4象限」までを,それぞれ該当する象限の中の任意の位置に記述せよ.

6 タイトルや凡例を弄る

6.1 軸のタイトルを消したり書き換えたり

デフォルトでは軸タイトルはaes()で設定した各軸の変数名がそのまま入るが,xlabylabを使って自分の好きなように変えることができる. 引数にNULLを設定すると軸タイトルを消せる.

以下では,x軸のタイトルを消し,y軸のタイトルを「がく長」に書き換えている.

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  xlab(NULL)+ylab("がく長")
plot(g)

6.2 凡例タイトルを書き換える

labs()を使う. 引数には,aes()で色を指定するときに使った引数に,書き換えたいタイトルを与える. 以下の例では,fillを使って色を与えているので,fill=****というのを引数としてlabelに与える.

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  xlab(NULL)+ylab("学長")+labs(fill="種類")
plot(g)

ちなみにlabsは引数として以下のものを取る.

項目 内容
title タイトル
subtitle サブタイトル
x x軸ラベル
y y軸ラベル
caption キャプション
fill またはcolor 凡例ラベルのタイトル

この通りに,xlabやylabもlabsでまとめて設定することもできる.

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  labs(x=NULL, y="がく長", fill="種類")
plot(g)

6.3 凡例を消す

theme(legend.position = "none")を使う.

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  xlab(NULL)+ylab("がく長")+
  theme(legend.position = "none")
plot(g)

6.4 軸タイトルや軸ラベル,凡例の文字サイズを換える

凡例を消した時と同じようにthemeを使う.引数には以下のようなものを入れる. axis.text.x=element_text(size=15) axis.text.y=element_text(size=15) axis.title.x=element_text(size=15) axis.title.y=element_text(size=15) legend.text=element_text(size=9)

g <- ggplot(d2,aes(x=種類,y=平均))+
  geom_bar(aes(fill=種類),stat="identity")+
  geom_errorbar(aes(ymin=平均-標準偏差, ymax=平均+標準偏差,width=0.3))+
  xlab("種類")+ylab("花弁の幅")+
  theme(legend.position = 'none')+
  theme(
    axis.title.x=element_text(size=15),
    axis.title.y=element_text(size=15),
    axis.text.x=element_text(size=10),
    axis.text.y=element_text(size=10),
    legend.text=element_text(size=5),
    legend.title = element_text(size=8)  )

plot(g)

themeの設定項目

themeは細かくいろいろ設定できる.設定できるものは以下の通り.

名前 説明 要素の型
text すべてのテキスト要素 element_text()
axis.title 両軸ラベルの体裁 element_text()
axis.title.x x軸ラベルの体裁 element_text()
axis.title.y y軸ラベルの体裁 element_text()
axis.text 両軸目盛ラベルの体裁 element_text()
axis.text.x x軸目盛ラベルの体裁 element_text()
axis.text.y y軸目盛ラベルの体裁 element_text()
legend.text 凡例項目の体裁 element_text()
legend.title 凡例タイトルの体裁 element_text()
plot.title タイトルの体裁 element_text()
strip.text 両方向ファセットラベルテキストの体裁 element_text()
strip.text.x 水平方向ファセットラベルテキストの体裁 element_text()
strip.text.y 垂直方向ファセットラベルテキストの体裁 element_text()
legend.position 凡例の位置 left, right, bottom, top, c(x,y) :x,yは0~1
legend.background 凡例の背景 element_rect(fill=“xxx”, color=“yyy”) fillは塗りつぶし,colorは枠線
plot.background プロット全体の背景 element_rect(fill=“xxx”, color=“yyy”)
panel.background プロット領域の背景 element_rect()
panel.border プロット領域の枠線 element_rect(linetype=“xxx”)
rect 全ての長方形要素 element_rect()
panel.grid.major 主目盛線 element_line()
panel.grid.major.x 主目盛線の垂直方向 element_line()
panel.grid.major.y 主目盛線の水平方向 element_line()
panel.grid.minor 補助目盛線 element_line()
panel.grid.minor.x 補助目盛線の垂直方向 element_line()
panel.grid.minor.y 補助目盛線の水平方向 element_line()
axis.line 軸に沿った線 element_line()
line すべての線要素 element_line()
引用(順序は改変しました):https://knknkn.hatenablog.com/entry/2019/02/23/181311
element_text()の設定項目
設定項目 element_text()の引数
角度 angle
水平位置 hjust(0:左揃え~1:右揃え)
垂直位置 vjust(0:下揃え~1:上揃え)
サイズ size
color
スタイル face(bold or italic)
フォントファミリー family
参考:http://mukkujohn.hatenablog.com/entry/2016/10/11/220722
element_xxxのその他の項目

element_rect(fill, color, size, linetype, inherit.blank) — 長方形

項目 内容
fill 塗りつぶしの色
color 枠の色

element_line(color, size, linetype, lineend, arrow, inherit.blank)— 線

element_blank() — 空 消したい要素にはこれを指定する

参考:https://heavywatal.github.io/rstats/ggplot2.html

6.5 表示範囲(x軸,y軸の変域)を変える

すでにこちらで説明したとおり,グラフの表示範囲を限定したい場合には,coord_cartesian()を使う.代表的な引数は以下の2つである.

  • xlim : x軸の表示範囲のベクトルデータ.c(最小値,最大値)で指定する.
  • ylim : y軸の表示範囲のベクトルデータ.c(最小値,最大値)で指定する.

6.6 目盛ラベルを変える

目盛ラベルを変えるには,scale_x_****scale_y_***を使う. 以下は,x軸の目盛りをsetosa, versicolor, virgnicaから,a, b, cに変え,y軸を普通の目盛から対数目盛に変えた例である.

g <- ggplot(data_iris)+
  geom_bar(aes(x=種類,fill=種類),stat="count") +
  scale_x_discrete(labels=c("a","b","c"))+
  scale_y_log10(limits=c(1,1000))
plot(g)

***の部分には,いずれも以下のものが入る.

*** 内容
discrete 離散目盛
continuous 連続目盛
log10 対数目盛
reverse 目盛の逆転
sqrt 平方根目盛

また,代表的な引数としては以下のものが入る.

引数 内容
labels 離散目盛のラベルを変える(以下のbreaksを併用すると,連続変数でも可能)
breaks 連続変数の目盛のうち指定したものだけを表示させる
limits 連続変数の表示範囲を指定したものにする.xlim,ylimと同じ効果.
name 変数の軸ラベルを変える.xlab,ylabと同じ効果.

ちなみに,xlimylimは内部ではscale_x_continuous(limits=...)scale_y_continuous(limits=)を使っている.このため,これらはデータそのものを除外しており,結果として表示範囲も変わるという仕組みになっている.単に表示範囲を変えたいだけであれば,coord_cartesian()を使う方がよい.

結局,軸タイトルを変える方法って,色々あるということである. xlabでもよいし,labs(x=)dでもよいし,scale_x_***(name=)でも変えれる.

6.7 凡例の各項目のラベルを書き換える.

グループ分けにfillを使っている場合は,sacle_fill_dicrete()を,Colorを使っている場合はscale_color_discrete()を使う.

g <- ggplot(data_iris)+
  geom_bar(aes(x=種類,fill=種類),stat="count")+
  scale_fill_discrete(label=c("花1","花2","花3"))
plot(g)

ggplot2で描画するときにエラーが出るケースとして,行末の「+」の付け忘れや消し忘れがある.もし思い通りにグラフが描画されない場合には,この点を確認してみるとよい.

ggplot2で色の指定をする際に設定できる色のリストは以下の通りである.

色のリスト
色のリスト

これら以外の色でもrgb関数を使って,赤,緑,青の光の3原色の比率を指定することで,任意の色を指定することもできる.第1引数が赤の強さ,第2引数が緑の強さ,第3引数が青の強さを示す.なお,rgb関数に与える数値は,0から1の数値にしている必要があるが,一般に色の階調は0~255の数字で表記されるため,以下の例のように,R,G,Bそれぞれに対応した数値を255で割っておく必要がある.例えば,赤と青の強さを255にして,緑の強さを0にすると,赤と青の混合色である紫色が得られる.

color = rgb(255/255, 255/255, 0/255) #紫色になる

その他,色の16進数コードを指定することもできる.

7 まとめ

ggplot2を使った描画はRでの様々な統計分析の結果をそのまま可視化できるので,描画の際に誤りが少なくなるため便利である上,デザインを統一するのも容易である. ただ,細かく設定できる分,設定項目が多く,正直私自身も覚えきれていない. なので,ggplot2を使った描画では都度ネットで「ggplot2 棒グラフ」や「ggplot2 ヒストグラム」などという形で検索を掛けて,自分が描画したいグラフに近いものをコピペして,それを少しずつ変えていくという方法が有効である.あるいは,ChatGPTにCSVファイルを添付したうえで「ggplot2で添付のCSVファイルを箱ひげ図にしてください」といった形で質問をすると,その都度コードを生成してくれるので,それを参考にするのもよいだろう.

重要なことは,自分で0から書くのはできなくても,人が書いたコードを読んで,何をしているかを理解できる能力を持っていることである.それが出来ていれば,ネットから見つけられるコードをコピペしてカスタマイズして自分が欲しい図を書かせることができるようになる.