例で私の質問を説明します。
サンプルデータ:
df <- data.frame(ID = c(1, 1, 2, 2, 3, 5), A = c("foo", "bar", "foo", "foo", "bar", "bar"), B = c(1, 5, 7, 23, 54, 202))
df
ID A B
1 1 foo 1
2 1 bar 5
3 2 foo 7
4 2 foo 23
5 3 bar 54
6 5 bar 202
私がやりたいのは、IDによって、Bの合計と、Aが「foo」の場合のBの合計を要約することです。次のようないくつかの手順でこれを行うことができます。
require(magrittr)
require(dplyr)
df1 <- df %>%
group_by(ID) %>%
summarize(sumB = sum(B))
df2 <- df %>%
filter(A == "foo") %>%
group_by(ID) %>%
summarize(sumBfoo = sum(B))
left_join(df1, df2)
ID sumB sumBfoo
1 1 6 1
2 2 30 30
3 3 54 NA
4 5 202 NA
ただし、sqliteで10 GB以上のメモリ不足データを処理するため、よりエレガントで高速な方法を探しています。
require(sqldf)
my_db <- src_sqlite("my_db.sqlite3", create = T)
df_sqlite <- copy_to(my_db, df)
mutate
を使用して新しいBfoo
列を定義することを考えました。
df_sqlite %>%
mutate(Bfoo = ifelse(A=="foo", B, 0))
残念ながら、これはデータベースの終わりには機能しません。
Error in sqliteExecStatement(conn, statement, ...) :
RS-DBI driver: (error in statement: no such function: IFELSE)
@hadleyのコメントを回答として書く
df_sqlite %>%
group_by(ID) %>%
mutate(Bfoo = if(A=="foo") B else 0) %>%
summarize(sumB = sum(B),
sumBfoo = sum(Bfoo)) %>%
collect
単一のdplyr
ステートメントで両方の合計を実行できます。
df1 <- df %>%
group_by(ID) %>%
summarize(sumB = sum(B),
sumBfoo = sum(B[A=="foo"]))
集計する代わりにカウントを行いたい場合、答えは多少異なります。特に条件付きカウント部分では、コードの変更はわずかです。
df1 <- df %>%
group_by(ID) %>%
summarize(countB = n(),
countBfoo = sum(A=="foo"))
df1
Source: local data frame [4 x 3]
ID countB countBfoo
1 1 2 1
2 2 2 2
3 3 1 0
4 5 1 0
行を合計するのではなく、行をカウントしたい場合は、関数に変数を渡すことができます:
_ df1 <- df %>%
group_by(ID) %>%
summarize(RowCountB = n(),
RowCountBfoo = n(A=="foo"))
_
n()
とnrow()
の両方でエラーが発生します。