2017年9月14日木曜日

reorderを使ってggplotの棒グラフの並び順を降順にする方法

# サンプルデータの作成
fruits <- c("apple","durian","orange")
count  <- c(2, 1, 3)
df <- data.frame(fruits, count)

df # 中身の確認


  fruits count
1  apple     2
2 durian     1
3 orange     3


このデータを使って、ggplotで棒グラフを描いてみると、

library(ggplot2)
ggplot(df, aes(x=fruits, y=count))

  + geom_bar(stat="identity")

並び順はデータのまま

当然ながら、棒の順番はデータ通りに、2、1、3と並びますね。

これをソートしたい場合は、reorderを使います↓

ggplot(df, aes(x=reorder(fruits, count), y=count)) +
  geom_bar(stat="identity")

reorderすると昇順に並ぶ

x軸はfruitsなんだけど、reorder関数の第二引数であるcountの値で並べ替えてから使ってね、という指定です。

で、次の課題です。

reorderを使うと、昇順で1、2、3という並びになりましたが、これを降順の3、2,1という並びにしたいときは、どうやればいいか。

データフレームをソートするときなんかに使うorder関数でいうところの「decreasing=TRUE」みたいな指定があればいいのですが、reorder関数にはそのようなオプションはなさそうです。

で、実はごく簡単で、reorderの第二引数(count)の値の正負が逆になれば、順番も逆になるじゃんという理屈です。

ggplot(df, aes(x=reorder(fruits, -count), y=count)) +
  geom_bar(stat="identity")

reorder関数の第二引数にマイナスをつければ降順にできる

無事、降順に並んでくれました。




Rのデータフレームから少数の行を削除する

例えば、↓こんなデータがあったとして、

# サンプルデータの作成
name  <- c("Anne", "Bob", "Carl", "Dann", "Eric", "Fred")
fruits <- c("orange", "apple", "orange", "durian", "orange", "apple")
df <- data.frame(name, fruits)

df # 中身を見てみる


  name fruits
1 Anne orange
2  Bob  apple
3 Carl orange
4 Dann durian
5 Eric orange
6 Fred  apple


みんなの好きな果物のデータだとして、1人しかいないような少数派の行は除去したいと。この例だと、ダンのドリアンを取り除きたいと。

ddplyを使って度数をカウントし、新たに度数(count)の列として追加(transform)。

library(plyr)
ddply(df, "fruits", transform, count=length(fruits))


  name fruits count
1  Bob  apple     2
2 Fred  apple     2
3 Dann durian     1
4 Anne orange     3
5 Carl orange     3
6 Eric orange     3


で、このcount列を条件として、データフレームをフィルタすればいいかなと。

dd <- ddply(df, "fruits", transform, count=length(fruits))
dd[ dd$count > 1, ] # 少数派の行を削除


  name fruits count
1  Bob  apple     2
2 Fred  apple     2
4 Anne orange     3
5 Carl orange     3
6 Eric orange     3


count列が邪魔だったら、後から削除しよう。

dd2 <- dd[ dd$count > 1, ]      # 少数派の行を削除
dd2[, colnames(dd2) != "count"] # countの列を削除


  name fruits
1  Bob  apple
2 Fred  apple
4 Anne orange
5 Carl orange
6 Eric orange

一応、できました。

でも、もっといいやり方があるような気がします・・・