计算R中的小计

时间:2010-11-05 08:32:42

标签: r subtotal

我有一个数据框,在R中有900,000行和11列。列名和类型如下:

column name: date / mcode / mname / ycode / yname / yissue  / bsent   / breturn / tsent   / treturn / csales
type:        Date / Char  / Char  / Char  / Char  / Numeric / Numeric / Numeric / Numeric / Numeric / Numeric

我想计算小计。例如,我想计算yname中每次更改的总和,并为所有数值变量添加小计。有160个不同的ynames,因此结果表应该告诉我每个yname的小计。我还没有对数据进行排序,但这不是问题,因为我可以以任何我想要的方式对数据进行排序。以下是我的数据摘录:

             date     mcode mname            ycode    yname   yissue bsent breturn tsent treturn csales
417572 2010-07-28     45740 ENDPOINT A        5772    XMAG  20100800     7       0     7       0      0
417573 2010-07-31     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417574 2010-08-04     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417575 2010-08-14     45740 ENDPOINT A        5772    XMAG  20100800     0       0     0       0      1
417576 2010-08-26     45740 ENDPOINT A        5772    XMAG  20100800     0       4     0       0      0
417577 2010-07-28     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417578 2010-08-04     45741 ENDPOINT L        5772    XMAG  20100800     2       0     2       0      0
417579 2010-08-26     45741 ENDPOINT L        5772    XMAG  20100800     0       4     0       0      0
417580 2010-07-28     46390 ENDPOINT R        5772    XMAG  20100800     3       0     3       0      1
417581 2010-07-29     46390 ENDPOINT R        5772    XMAG  20100800     0       0     0       0      2
417582 2010-08-01     46390 ENDPOINT R        5779    YMAG  20100800     3       0     3       0      0
417583 2010-08-11     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417584 2010-08-20     46390 ENDPOINT R        5779    YMAG  20100800     0       0     0       0      1
417585 2010-08-24     46390 ENDPOINT R        5779    YMAG  20100800     2       0     2       0      1
417586 2010-08-26     46390 ENDPOINT R        5779    YMAG  20100800     0       2     0       2      0
417587 2010-07-28     46411 ENDPOINT D        5779    YMAG  20100800     6       0     6       0      0
417588 2010-08-08     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417589 2010-08-11     46411 ENDPOINT D        5779    YMAG  20100800     0       0     0       0      1
417590 2010-08-26     46411 ENDPOINT D        5779    YMAG  20100800     0       4     0       4      0

我应该在这里使用什么功能?也许像SQL group by

7 个答案:

答案 0 :(得分:10)

行。假设您的数据位于名为foo的数据框中:

> head(foo)
             date mcode      mname ycode yname   yissue bsent breturn tsent
417572 2010/07/28 45740 ENDPOINT A  5772  XMAG 20100800     7       0     7
417573 2010/07/31 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417574 2010/08/04 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417575 2010/08/14 45740 ENDPOINT A  5772  XMAG 20100800     0       0     0
417576 2010/08/26 45740 ENDPOINT A  5772  XMAG 20100800     0       4     0
417577 2010/07/28 45741 ENDPOINT L  5772  XMAG 20100800     2       0     2
       treturn csales
417572       0      0
417573       0      1
417574       0      1
417575       0      1
417576       0      0
417577       0      0

然后,这将汇总数据中的数字列:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum)
  yname bsent breturn tsent treturn csales
1  XMAG    14       8    14       0      6
2  YMAG    11       6    11       6      5

那是使用你在Q中包含的数据片段。我使用公式接口aggregate(),这在这个例子中更好一点,因为你不需要所有的foo$位在您希望聚合的变量名称上。如果您的完整数据集中缺少数据(NA),那么您需要添加一个额外的参数na.rm = TRUE,它将传递给sum(),如下所示:

> aggregate(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data = foo, 
+           FUN = sum, na.rm = TRUE)

答案 1 :(得分:4)

plyr库,可以轻松扩展到其他数据类:

> library(plyr)
> result.2 <- ddply(df$a, .(df$b), sum)
> result.2
  df.b V1
1 down 30
2   up 25

答案 2 :(得分:4)

您还可以使用xtabstapply

xtabs(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data)

tapply(data$bsent, data$yname, sum)

答案 3 :(得分:3)

如果您的数据很大并且速度很重要,我建议使用R函数rowsum,这要快得多。我应用了答案中建议的3种方法(f1 = aggregate,f2 = ddply,f3 = tapply),将它与f4 = rowsum进行比较,这是我发现的:

   test replications elapsed relative
4 f4()          100   0.033     1.00
3 f3()          100   0.046     1.39
1 f1()          100   0.165     5.00
2 f2()          100   0.605    18.33

如果有人想要更详细地探索,我在下面添加了我的代码。

library(plyr);
library(rbenchmark);

val  = rnorm(50);
name = rep(letters[1:5], each = 10);
data = data.frame(val, name);

f1 = function(){aggregate(data$val, by=list(data$name), FUN=sum)}
f2 = function(){ddply(data, .(name), summarise, sum = sum(val))}
f3 = function(){tapply(data$val, data$name, sum)}
f4 = function(){rowsum(x = data$val, group = data$name)}

benchmark(f1(), f2(), f3(), f4(),
          columns=c("test", "replications", "elapsed", "relative"),
          order="relative", replications=100)

答案 4 :(得分:2)

您可以使用aggregate

例如,说你有

val = rnorm(50)
name = rep(letters[1:5], each=10)
data <- data.frame(val, name)

然后你可以做

aggregate(data$val, by=list(data$name), FUN=sum)

答案 5 :(得分:2)

有一个名为sqldf的R包,它允许您在R data.frames上使用SQL命令。 除了你已经说过的,GROUP BY会很好。您可以轻松地将数据存储在本地MySQL数据库中,并使用包RMySQL连接到R(您可以使用大多数其他DBMS,但MySQL是最容易设置的)。

据我所知,plyr也是一个很棒的包。但是从你问的方式和你的问题与GROUP BY的比较,我想你对SQL有所了解,所以使用它可能对你来说更容易。有一些像dbReadTable这样的舒适函数,如果你的数据变得越来越大,你只能选择数据的子部分来运行你真正需要的分析。

答案 6 :(得分:2)

当我试图找到类似问题的答案时,Google并不是超级有用。我想我可以在下面将PlayerInitClass p = new PlayerInitClass(); 包与library(janitor)split()共享我的解决方案。

我的用例是运行一个脚本,该脚本将从许多不同的人那里获取CC费用,由一个人进行审核。

purrr::map_df()