web-dev-qa-db-ja.com

Rでデータをグループ化/ビン/バケット化し、バケットごとのカウントとバケットごとの値の合計を取得する

データをバケット/グループ/ビン化したい:

C1             C2       C3
49488.01172    0.0512   54000
268221.1563    0.0128   34399
34775.96094    0.0128   54444
13046.98047    0.07241  61000
2121699.75     0.00453  78921
71155.09375    0.0181   13794
1369809.875    0.00453  12312
750            0.2048   43451
44943.82813    0.0362   49871
85585.04688    0.0362   18947
31090.10938    0.0362   13401
68550.40625    0.0181   14345

C2値でバケット化したいが、バケットを定義したい。 <= 0.005、<=。010、<=。014など。ご覧のとおり、バケットの間隔は不均一になります。バケットごとのC1の数と、すべてのバケットのC1の合計が必要です。

私はRのかなり新しいユーザーなので、どこから始めればいいのかわかりません。コードを理解するのを手伝ってくれる人や、自分のニーズに合った例を紹介してくれる人はいますか?

編集:別の列C3を追加しました。バケットごとのC3の合計と、バケットごとのC1の合計およびカウントが同時に必要です

10
Freewill

コメントから、「C2」は_%_がサフィックスとして付いた「文字」列のようです。グループを作成する前に、subを使用して_%_を削除し、「数値」(_as.numeric_)に変換します。変数「グループ」は、関数cutbreaks(グループバケット/間隔)およびlabels(必要な場合)を使用して作成されます(transform(df,...))グループラベル)引数。グループ変数が作成されると、「グループ」による「C1」のsumおよび「グループ」内の要素の「カウント」は、「ベースR」のaggregateを使用して実行できます。

_df1 <-  transform(df, group=cut(as.numeric(sub('[%]', '', C2)), 
    breaks=c(-Inf,0.005, 0.010, 0.014, Inf),
      labels=c('<0.005', 0.005, 0.01, 0.014)))

 res <- do.call(data.frame,aggregate(C1~group, df1, 
        FUN=function(x) c(Count=length(x), Sum=sum(x))))

 dNew <- data.frame(group=levels(df1$group))
 merge(res, dNew, all=TRUE)
 #   group C1.Count    C1.Sum
 #1 <0.005        2 3491509.6
 #2  0.005       NA        NA
 #3   0.01        2  302997.1
 #4  0.014        8  364609.5
_

または、_data.table_を使用できます。 setDTは、_data.frame_を_data.table_に変換します。 _by=_で「グループ化」変数を指定し、_list(_内の2つの変数「Count」と「Sum」を要約/作成します。 _.N_は、各「グループ」内の要素の数を示します。

_ library(data.table)
  setDT(df1)[, list(Count=.N, Sum=sum(C1)), by=group][]
_

または、dplyrを使用します。 _%>%_は、LHSをRHS引数に接続し、それらを結合します。 _group_by_を使用して「グループ」変数を指定し、次に_summarise_each_またはsummariseを使用して、関連する列のサマリーカウントとsumを取得します。 _summarise_each_は、複数の列がある場合に役立ちます。

_ library(dplyr)
 df1 %>%
      group_by(group) %>% 
      summarise_each(funs(n(), Sum=sum(.)), C1)
_

更新

新しいデータセットの使用df

_df1 <- transform(df, group=cut(C2,  breaks=c(-Inf,0.005, 0.010, 0.014, Inf),
                             labels=c('<0.005', 0.005, 0.01, 0.014)))

res <- do.call(data.frame,aggregate(cbind(C1,C3)~group, df1, 
       FUN=function(x) c(Count=length(x), Sum=sum(x))))
res
#  group C1.Count    C1.Sum C3.Count C3.Sum
#1 <0.005        2 3491509.6        2  91233
#2   0.01        2  302997.1        2  88843
#3  0.014        8  364609.5        8 268809
_

上記のようにmergeを実行できます。

dplyrアプローチは、追加の変数を指定することを除いて同じです。

_ df1%>%
      group_by(group) %>%
       summarise_each(funs(n(), Sum=sum(.)), C1, C3)
 #Source: local data frame [3 x 5]

 #  group C1_n C3_n    C1_Sum C3_Sum
 #1 <0.005    2    2 3491509.6  91233
 #2   0.01    2    2  302997.1  88843
 #3  0.014    8    8  364609.5 268809
_

データ

_df <-structure(list(C1 = c(49488.01172, 268221.1563, 34775.96094, 
13046.98047, 2121699.75, 71155.09375, 1369809.875, 750, 44943.82813, 
85585.04688, 31090.10938, 68550.40625), C2 = c("0.0512%", "0.0128%", 
"0.0128%", "0.07241%", "0.00453%", "0.0181%", "0.00453%", "0.2048%", 
"0.0362%", "0.0362%", "0.0362%", "0.0181%")), .Names = c("C1", 
"C2"), row.names = c(NA, -12L), class = "data.frame")
_
12
akrun