Rでgroup_concatする方法をまとめる
この記事は R Advent Calendar 2016 4 日目の記事です。
group_concat について
MySQL などの 多くの SQL には group_concat
という関数があります。
どういう関数かというと、複数のレコードを一つにまとめるもので、たとえば以下のようなデータを考えます。
### サンプルデータ id <- c(1, 1, 2, 3, 3) name <- c("apple", "orange", "orange", "orange", "apple") df <- data.frame(id, name)
id | name |
---|---|
1 | apple |
1 | orange |
2 | orange |
3 | orange |
3 | apple |
ここから、id 毎にまとめて次のような形にするの SQL の group_concat
関数です。
id | name |
---|---|
1 | apple, orange |
2 | orange |
3 | apple, orange |
MySQL での使い方など、group_concat
そのものについて知りたい方は例えば以下を参照してください。
文字列の処理をやっているとたまに必要がでてくるこの処理ですが、今回はこの group_by
の処理を R で行うことを考えます。
この記事では 4 通りの方法を紹介しますが、最初の3つについては基本的な考え方は同じです。
方法 1 base::aggregate()
aggregate(data = df, name ~ id, FUN = function(t) paste(unique(t)))
# id name #1 1 apple,orange #2 2 orange #3 3 orange,apple
一つ目の方法は R の標準の集計関数である base::aggregate
を使う方法です。
この関数では集計するための関数を FUN =
オプションの中で自分で指定する必要がありますが、
文字列の集計なので paste()
くっつけます。paste()
に unique()
をかませてあるのは、
たとえば id = 1, name = apple が複数レコードあるときにそれを一つだけにしたいからです。
こうすると SQL の group_concat
と挙動が同じになりますが、複数あうときにそれを一つのセルに押し込みたいときは unique()
を外せば OK です。
方法 2 dplyr::group_by %>% sumarise
library(dplyr) group_by(id) %>% summarise(name = paste(unique(name), collapse = ","))
# id name #1 1 apple,orange #2 2 orange #3 3 orange,apple
二つ目の方法は R のデータ処理ではもはやおなじみの {dplyr} パッケージを使う方法です。 {dplyr} パッケージでのデータ処理に関する基本的なことは以下を参考にしてください。
{dplyr} パッケージで集計を行う場合、最初にまとめたい変数で group_by()
でまとめ、
summarise()
の中で集計の関数を指定します。paste()
以下の記述は基本的には #方法 1 と同じ同じですが、
ここではあえて collapse =
をオプションとしていれています。ここを変更すればもちろんセパレータを変更することが可能です。
方法 3 {data.table}
library(data.table) setDT(df)[, .(name = paste(unique(name))), by = id]
# id name #1 1 apple,orange #2 2 orange #3 3 orange,apple
三つ目の方法は {data.table} パッケージを使う方法です。このパッケージは大きなデータを高速に読み込むことで有名なパッケージですが、 簡単な前処理もできます。考え方は上 2 つと同じです。 {data.table} パッケージでのデータ処理についての詳細は以下を参考にしてください。
方法 4 {sqldf}
library(sqldf) query <- "select id, group_concat(name) as name from df group by id" sqldf(query)
# id name #1 1 apple,orange #2 2 orange #3 3 orange,apple
四つめの方法は、やや邪道ですが SQL クエリをそのまま書いてしまう方法です。
使うパッケージは {sqldf} パッケージで、sqldf()
の中に SQL クエリを文字列で与えてやればそれを実行してくれます。
まとめ
R で SQL の group_concat
にあたる処理を実行する方法をいくつか紹介しました。
paste()
の部分を {stringr} パッケージで置き換えてみるなど、いろいろな工夫ができるかと思います。
明日のRアドカレは
takeshi0406 さんによる「Rプログラマーのための関数型プログラミングの学び方」です。楽しみですね。