ggplotで他の変数を基準に並び替える
数値で並び替える場合
以下のようなグラフで考える。
library(tidyverse) data(diamonds) # データ作成 df = diamonds %>% group_by(clarity, cut) %>% summarise(n = n()) %>% ungroup() # わかりやすいものだけ抽出 df_filtered = df %>% filter(clarity %in% c('SI2', 'VVS2', 'IF')) # clarityの標準の順番 df_filtered %>% ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity)
このとき、各facetでの棒グラフはデータフレームでcut
が出てきた順で、グラフの下からFair
,Good
,...といった表示になっている。
このとき、各facet毎に、棒グラフの長さ順で並び替えたい。
factor変数に対して、他の変数を基準に並び替えたい場合は一般的にfct_reorder
で並び替える。今回は2変数を基準にするのでfct_reorder2
を使う。
df_filtered %>% mutate(cut = fct_reorder2(cut, n, clarity)) %>% # nで並び替える ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity)
結果を見ると、並び替えは起きているようだが上手くいっていない。
データを出力してみると、以下のようになっており先程と同様にデータフレームでcut
が出てきた順で、グラフの下からIdeal
,Fair
,...といった表示になっている。
df_filtered %>% mutate(cut = fct_reorder2(cut, n, clarity)) %>% # nで並び替える arrange(cut)
グラフで使う場合はreorder_within
を使う。
df_filtered %>% mutate(cut = reorder_within(cut, n, clarity)) %>% # n, clarityで並び替える ggplot(aes(n, cut, fill = clarity)) + geom_col() + scale_y_reordered() + # __で結合されているのを削除 facet_wrap(. ~ clarity, scales = 'free_y') # 自分のfacet変数のみ
これは内部的に指定した変数(cut
, clarity
)を結合した新たな変数を用いてn
で並び替えをおこなっている。
そのため、新たな結合された変数cut__clarity
の出た順になるため各clarity
のfacetでは自分のclarity
が入っているcut__clarity
以外はデータがないので「出た順に並び替える」ことができる。
df_filtered %>% mutate(cut = reorder_within(cut, n, clarity)) %>% arrange(cut)
なお、コード中にscale_y_reordered
および、scales = 'free_y'
を追加しているが、前者は「表示を結合状態から元に戻す」働きがある。
また、後者はデータがない部分を非表示にする働きがある。今回の場合、cut__clarity
が自facet内のclarity
以外はデータがないが表示自体はされるためscales = 'free_y'
で非表示にできる。
これらを外して表示すると意味がわかりやすい。
df_filtered %>% mutate(cut = reorder_within(cut, n, clarity)) %>% # n, clarityで並び替える ggplot(aes(n, cut, fill = clarity)) + geom_col() + # scale_y_reordered() + # __で結合されているのを削除 facet_wrap(. ~ clarity) #, scales = 'free_y')
facetを並び替える
facetは一般的にfactor
となっている。これを別変数を基準にしてfacetを並び替える。
データとして、clarity
毎に1文字目を基準にgroupを作り、このgroup毎にclarity
のfacetを並び替えて先程と同様のグラフを作成する。
df2 = diamonds %>% mutate(clarity_group = substr(clarity, 1, 1)) %>% group_by(clarity_group, clarity, cut) %>% summarise(n = n()) %>% ungroup() df2 %>% distinct(clarity_group, clarity) %>% arrange(clarity_group, clarity)
これをそのまま出力すると、当たり前だがclarity
の順でfacetが表示される。
df2 %>% ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity)
これを同じclarity_group
を固めて表示したい。
facetに2軸を指定する方法
1つ目の方法として、clarity_group
もfacetに表示する方法が考えられる。
df2 %>% ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity_group + clarity)
目的通りclarity_group
が固まって表示されているが、facetと凡例の順が一致していないし、表示があまりきれいではない。
fct_reorderを使う方法
前節でちらっと出たfct_reorder
を使い、clarity
をclarity_group
基準に並び替える。
df2 %>% mutate(clarity = fct_reorder(clarity, clarity_group)) %>% ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity)
この場合は、facetと凡例の順番が一致している。
任意の順にする
また、今回clarity_group
はchar
なのでアルファベット順だが任意のclarity_group
順にしたい場合は、factor
に変換する。
この際、そのままfct_reorder
に指定すると型エラーになるのでas.numeric
でnumericに変換する必要がある。なお、factorをnumericにするとlevel部分の数値となる。
df2 %>% mutate(clarity_group = factor(clarity_group, levels = c('S', 'V', 'I')), clarity = fct_reorder(clarity, as.numeric(clarity_group))) %>% # numericにする ggplot(aes(n, cut, fill = clarity)) + geom_col() + facet_wrap(. ~ clarity)