★データ解析備忘録★

ゆる〜い技術メモ

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 毎にまとめて次のような形にするの SQLgroup_concat 関数です。

id name
1 apple, orange
2 orange
3 apple, orange

MySQL での使い方など、group_concat そのものについて知りたい方は例えば以下を参照してください。

d.hatena.ne.jp

文字列の処理をやっているとたまに必要がでてくるこの処理ですが、今回はこの 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 が複数レコードあるときにそれを一つだけにしたいからです。 こうすると SQLgroup_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} パッケージでのデータ処理に関する基本的なことは以下を参考にしてください。

qiita.com

{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} パッケージでのデータ処理についての詳細は以下を参考にしてください。

qiita.com

方法 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 で SQLgroup_concat にあたる処理を実行する方法をいくつか紹介しました。 paste() の部分を {stringr} パッケージで置き換えてみるなど、いろいろな工夫ができるかと思います。

明日のRアドカレは

takeshi0406 さんによる「Rプログラマーのための関数型プログラミングの学び方」です。楽しみですね。