StatsBeginner: 初学者の統計学習ノート

統計学およびR、Pythonでのプログラミングの勉強の過程をメモっていくノート。たまにMacの話題。

折れ線グラフの端っこにラベルを付けるやつ(ggplot2)

f:id:midnightseminar:20200831132131p:plain


最近になって遅ればせながらggplot2を頻繁に使うようになってきました。
で、↑こういうふうに、折れ線の端っこにラベルを置きたいと思いました。白黒の記事原稿で4本もの折れ線を重ねるのは見づらいのでそもそもやめたほうがいいですが、人生いろいろあるわけです。
そして、ggplot2の線種は見分けがつきにくいので、凡例だけで示すのは難しい。


ググると解説ブログがいくつか見つかりますが、パット見では何をやっているのか意味がわかりやすくない気もしたので、メモしておきます。
考え方としては、

  • ggplot2の他にggrepelパッケージを入れておく。これは互いに重ならない「いい感じのラベル」を書くときに使うもの。
  • x軸の範囲を左右に少し広げておく。
  • 折れ線の末端を「点」とみなして、そこに新たに散布図を描くようなイメージで、geom_text_repelでテキストを置く。
  • 散布図にnudge(点とラベルの距離)を設定することで、強制的にラベルを左右方向にズラす。するとggrepelの機能で、「点」とラベルが線で結ばれるようになる。(点とラベルというか、正確に言うと、geom_text_repelは座標に文字を配置する散布図を描くものだが、座標で指定した位置が点として認識されている。)


という手順になります。「折れ線の端を点とみなした散布図を描いて、そこに指示線つきのラベルを添える」という考え方がポイントだと思います。
イメージとしては、


f:id:midnightseminar:20200831133007p:plain


こういうタイプのグラフをまず思い浮かべればよい。この、ラベルと点が線で繋がれてる感じのものを、折れ線グラフの端っこに重ねてやって、派手な赤点を目立たないようにしてやればいいわけです。


冒頭のグラフは以下のようなコードで描きましたが、

library(ggplot2)
library(ggrepel)

dat %>%
  ggplot(aes(x=YEAR, y=FREQ)) +
  geom_line(aes(size=CODE, linetype=CODE, colour=CODE)) +   # ここ書いとかないとmanual設定も動かない
  theme_classic() +
  geom_text_repel(
    data = dat %>% filter(YEAR==max(YEAR)),    # 折れ線の右端にうつ点
    aes(x=YEAR, y=FREQ, label = CODE),
    nudge_x = 4,
    segment.alpha = 0.5,
    size = 6,
    family="MS Gothic") + 
  geom_text_repel(
    data = dat %>% filter(YEAR==min(YEAR)),
    aes(x=YEAR, y=FREQ, label = CODE),
    nudge_x = -4,                 #  点とラベルの距離
    segment.alpha = 0.5,     # 間に引かれる線をすこし薄くする
    size = 6,                          # ラベルの大きさ
    family="MS Gothic") +  # 日本語を表示するときはフォント指定しておく
  scale_linetype_manual(values = c("solid", "dashed", "solid", "twodash")) +         # 線のタイプ
  scale_size_manual(values = c(1.1,0.9,1.3,0.9)) +                                                      # 線の太さ
  scale_color_manual(values = c('#000000','#000000','#BBBBBB','#000000')) +  # 線の色
  scale_x_continuous(limits=c(1960, 2023),
                     breaks=c(1970, 1980, 1990, 2000, 2010, 2020)) + 
  theme(text = element_text(family="MS Gothic"),
        axis.text=element_text(size=15,color="black"),
        axis.title.y = element_text(size=15,color="black"),
        legend.position = 'none') + 
  labs(x="", y="\n頻度/掲載論文数\n", color = "")
  • geom_lineの行で、線種、色、太さを分けるグループを指定しておく。
  • theme_classicはシンプルなスタイルを選択してる設定。
  • geom_text_repelを2回やってますが、1つ目はxが最大の点を利用して右側にラベルを書く作業、2つ目はxが最小の点を利用して左側にラベルを書く作業です。要するにこのグラフは、1つの折れ線と2つの散布図が重なったものってことです。
  • nudgeしない場合、点の座標にそのままラベルが書かれることになり、ラベルのテキスト同士が重なる場合だけggrepelの機能でずらされて、場合によっては指示線が出るのですが、正負方向に4年分だけnudgeする設定にしておくことで、強制的にこの指示線を出すようにします。
  • scale_linetype_manual、scale_size_manual、scale_color_manualは、線の種類・太さ・色を手動設定するもので、これを設定しなければ、グループ変数(ここではCODE)ごとに適当に割当られます。
  • x軸のデータは1965年から2017年までしかないのですが、ラベルを表示する領域を確保するために、scale_x_continuousのlimitsで左右の範囲を少し広げています。
  • legend.position = 'none'で凡例は無しにしている。


f:id:midnightseminar:20200831132131p:plain