题
我有一个数据框,在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
?
解决方案
好的。假设您的数据在名为的数据框中 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)
其他提示
或者 plyr
库,其他数据类很容易扩展:
> library(plyr)
> result.2 <- ddply(df$a, .(df$b), sum)
> result.2
df.b V1
1 down 30
2 up 25
您也可以使用 xtabs
或者 tapply
:
xtabs(cbind(bsent, breturn, tsent, treturn, csales) ~ yname, data)
tapply(data$bsent, data$yname, sum)
如果您的数据很大并且速度很重要,我建议使用R函数rowsum,这要快得多。我应用了3种方法(f1 =聚集,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)
您可以使用 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)
有一个称为SQLDF的R软件包,它使您可以在R data.frames上使用SQL命令。此外,就像您已经说过的那样,Group By会很好。您可以轻松地将数据存储在本地MySQL数据库中,并使用软件包RMYSQL连接到R(您也可以使用大多数其他DBMS,但MySQL最容易设置)。
据我所知,Plyr也是一个很棒的包装。但是,从您提出和比较您的问题与分组的方式,我想您对SQL有所了解,因此使用此问题可能更容易。还有舒适的功能,例如Dbreadtable,此外,如果您的数据生长更大,则只能选择数据的子部分,只使用您真正需要的内容来运行分析。