mikutaifukuの雑記帳

個人的な雑記帳。データ分析とか読んだ本の感想とか。

ggplot2でfacetごとのヒストグラムに色んな情報を付与する① 〜基本作図編〜

概要

大した内容ではないですが、仕事で使ったので自分用メモです。なので、やや適当です。

以下のようなグラフを作ります。

f:id:mikutaifuku:20190511035424p:plain

具体的には、以下のような特徴を備えたグラフです。

  • facetごとのヒストグラムに、要約統計量(平均値、最小値、最大値)の線を引く
  • 各グラフの右上に、テキストで要約統計量を出力する
  • グループ名の後ろに(n = xx)というような、n数を付与する

データ

データはirisデータを使用します。

グループごとの要約統計量

SpeciesごとにSepal.Lengthの要約統計用を計算します。また、出力用のテキストを作成します。

library(tidyverse)
df <- iris %>% select(x = Sepal.Length, group = Species)
df_summary <- df %>% 
    group_by(group) %>% 
    summarise(n = n(),
              mean_x = mean(x),
              min_x = min(x),
              max_x = max(x),
              sd_x =sd(x)) %>% 
    mutate(group_label = paste0(group, " (n = ", n, ")"),
           mean_label = paste0("Mean : ", round(mean_x, 2)),
           sd_label = paste0("SD : ", round(sd_x, 2)),
           min_label = paste0("Min : ", round(min_x, 2)),
           max_label = paste0("Max : ", round(max_x, 2))) %>% 
    mutate(text_label = paste0(mean_label,"\n",sd_label,"\n",min_label,"\n",max_label))

作成したデータは以下のような感じです。

> df_summary
# A tibble: 3 x 12
  group          n mean_x min_x max_x  sd_x group_label         mean_label  sd_label  min_label max_label text_label                                    
  <fct>      <int>  <dbl> <dbl> <dbl> <dbl> <chr>               <chr>       <chr>     <chr>     <chr>     <chr>                                         
1 setosa        50   5.01   4.3   5.8 0.352 setosa (n = 50)     Mean : 5.01 SD : 0.35 Min : 4.3 Max : 5.8 "Mean : 5.01\nSD : 0.35\nMin : 4.3\nMax : 5.8"
2 versicolor    50   5.94   4.9   7   0.516 versicolor (n = 50) Mean : 5.94 SD : 0.52 Min : 4.9 Max : 7   "Mean : 5.94\nSD : 0.52\nMin : 4.9\nMax : 7"  
3 virginica     50   6.59   4.9   7.9 0.636 virginica (n = 50)  Mean : 6.59 SD : 0.64 Min : 4.9 Max : 7.9 "Mean : 6.59\nSD : 0.64\nMin : 4.9\nMax : 7.9"

元データの加工

元データに各グループのn数を付与します。

df_plot <- df %>% 
    left_join(df_summary %>% select(group, group_label), by = "group")

作成したデータは以下のような感じです。

> head(df_plot)
    x  group     group_label
1 5.1 setosa setosa (n = 50)
2 4.9 setosa setosa (n = 50)
3 4.7 setosa setosa (n = 50)
4 4.6 setosa setosa (n = 50)
5 5.0 setosa setosa (n = 50)
6 5.4 setosa setosa (n = 50)

プロット(完成)

いい感じのグラフできました。

x_pos <- max(df_summary$max_x)
y_pos <- Inf

g <- ggplot(df_plot, aes(x)) + 
    theme_minimal() +
    geom_histogram(fill="darkgrey") + 
    geom_vline(data=df_summary, aes(xintercept=mean_x), linetype="dashed", color="darkred") + 
    geom_vline(data=df_summary, aes(xintercept=min_x), linetype="dashed", color="darkred") + 
    geom_vline(data=df_summary, aes(xintercept=max_x), linetype="dashed", color="darkred") + 
    geom_text(data=df_summary, aes(x=x_pos, y=y_pos, label=text_label),
              colour="darkred", inherit.aes=FALSE, vjust="inward", hjust="inward") +
    facet_wrap(~group_label, ncol=1) +
    labs(x="Sepal.Length")

plot(g)

f:id:mikutaifuku:20190511035424p:plain

参考

いつも有益な情報を提供してくださる、株式会社ホクソエムのブログを参考にしました。 blog.hoxo-m.com

テキストがグラフ内におさまる方法を参考にしました。

ggplot(df, aes(x, y)) +
  geom_text(aes(label = text), vjust = "inward", hjust = "inward")

ggplot2.tidyverse.org

さいごに

パート②では、加工処理とプロット処理を関数化し、プロットを全ての変数に対して繰り返し行います。

雰囲気で作成したので、間違っていたら、遠慮なくご指摘ください。