ggplot2: 複数のデータセットの棒グラフを1枚の図にまとめる方法
複数のデータセットがあった場合、データセットごとに色を変えて区別することで、棒グラフを1つの図にまとめる方法の紹介です。
具体的には、下図のような棒グラフです。2つのシーズン (season) ごとにデータセットがあり、シーズンを色で区別することで、1枚の図にまとめています。
データセットごとに異なる色で棒グラフを作成
ggplot2 において、データセットごとに塗り分けるコードは単純です。データセット1つの場合と、ほとんど変わりません。
g <- ggplot(plot_data, aes(percentage, buki, fill = season)) +
geom_col(position = "dodge")
g + theme(text = element_text(family = "HiraKakuProN-W3")) +
scale_fill_discrete(breaks = c("drizzle2023", "chill2023")) +
labs(x = "使用率(%)", y = "",
title = "ブキ使用率の比較(上位20, chill2023)", subtitle = "ナワバリ Drizzle 2023 - Chill 2023")
まず、ggplot() に指定する aes() の中で、 「fill = season」と、season の値で塗ることを指定します。続いて、 geom_col() の引数に 「position = "dodge"」を指定するだけです。
* scale_fill_discrete(breaks = c("drizzle2023", "chill2023")) の部分は、凡例のデータセットの並びを指定しています。この指定がないとアルファベット順になるため、chill2023 が上に来てしまいます。
大変なのはプロット用データの整形
このような棒グラフを作成する場合、大変なのは、データのテーブルを整形してプロット用のデータを準備する作業です。
上記でプロット用データとして使用した plot_data は、下記のようなテーブルになっています。テーブルが2つあるわけではなく、 season の列の値で区別するように、join() と gather() を使ってまとめる必要があります。
> plot_data
# A tibble: 40 × 4
weapon buki season percentage
<chr> <fct> <chr> <dbl>
1 fincent_hue フィンセント・ヒュー drizzle2023 NA
2 fincent_hue フィンセント・ヒュー chill2023 1.45
3 variableroller ヴァリアブルローラー drizzle2023 1.70
4 variableroller ヴァリアブルローラー chill2023 1.45
5 sharp シャープマーカー drizzle2023 2.15
6 sharp シャープマーカー chill2023 1.66
7 splatroller スプラローラー drizzle2023 1.54
8 splatroller スプラローラー chill2023 1.67
9 pablo パブロ drizzle2023 1.81
10 pablo パブロ chill2023 1.72
# … with 30 more rows
# ℹ Use `print(n = ...)` to see more rows
元データとなるテーブルは、下記の2つです。この2つのテーブルから上記の1つのテーブルをイメージするのが、最初はなかなか大変かと思います。
> weapon_nawabari_drizzle2023
# A tibble: 101 × 3
weapon total percentage
<chr> <dbl> <dbl>
1 promodeler_rg 77082 6.22
2 sshooter_collabo 47714 3.85
3 sshooter 41190 3.32
4 lact450 38169 3.08
5 furo 36061 2.91
6 nzap89 35047 2.83
7 sharp_neo 31876 2.57
8 bold 31411 2.53
9 momiji 30076 2.43
10 wakaba 29244 2.36
# … with 91 more rows
# ℹ Use `print(n = ...)` to see more rows
> weapon_nawabari_chill2023
# A tibble: 110 × 3
weapon total percentage
<chr> <dbl> <dbl>
1 maneuver_collabo 39669 7.35
2 promodeler_rg 31346 5.81
3 sshooter_collabo 16343 3.03
4 furo 15410 2.85
5 sshooter 14624 2.71
6 52gal 13780 2.55
7 lact450 12924 2.39
8 liter4k 12666 2.35
9 bold 12512 2.32
10 nzap89 12237 2.27
# … with 100 more rows
# ℹ Use `print(n = ...)` to see more rows
それぞれに、 weapon と percentage の列があります。total の列は使わないので除外して、percentage の名前をリネームしてから、weapon で left_join() すると、下記のようになります。
# A tibble: 110 × 4
weapon buki drizzle2023 chill2023
<chr> <chr> <dbl> <dbl>
1 52gal .52ガロン 2.07 2.55
2 96gal .96ガロン 0.185 0.193
3 96gal_deco .96ガロンデコ 0.335 0.367
4 bold ボールドマーカー 2.53 2.32
5 bold_neo ボールドマーカーネオ 0.775 0.825
6 bottlegeyser ボトルガイザー 0.557 0.399
7 bottlegeyser_foil ボトルガイザーフォイル NA 0.964
8 heroshooter_replica ヒーローシューター レプリカ 1.39 1.18
9 jetsweeper ジェットスイーパー 0.306 0.282
10 jetsweeper_custom ジェットスイーパーカスタム 0.974 0.867
# … with 100 more rows
# ℹ Use `print(n = ...)` to see more rows
これに gather() を使って「gather(ends_with("2023"), key = "season", value = "percentage")」とまとめたものが前述の plot_data です。
* gather 後、さらに top_n() で上位20を取り出して、fct_reorder() で並び順を指定しています。