R 将聚合值连接回原始数据帧

R 将聚合值连接回原始数据帧,r,plyr,R,Plyr,我反复使用的设计模式之一是在数据帧上执行“分组方式”或“拆分、应用、合并(SAC)”,然后将聚合数据连接回原始数据。例如,在计算多个州和县的数据框架中每个县与州平均值的偏差时,这是有用的。我的合计计算很少只是一个简单的平均值,但它是一个很好的例子。我经常用以下方法解决这个问题: require(plyr) set.seed(1) ## set up some data group1 <- rep(1:3, 4) group2 <- sample(c("A","B","C"), 12

我反复使用的设计模式之一是在数据帧上执行“分组方式”或“拆分、应用、合并(SAC)”,然后将聚合数据连接回原始数据。例如,在计算多个州和县的数据框架中每个县与州平均值的偏差时,这是有用的。我的合计计算很少只是一个简单的平均值,但它是一个很好的例子。我经常用以下方法解决这个问题:

require(plyr)
set.seed(1)

## set up some data
group1 <- rep(1:3, 4)
group2 <- sample(c("A","B","C"), 12, rep=TRUE) 
values <- rnorm(12)
df <- data.frame(group1, group2, values)

## got some data, so let's aggregate

group1Mean <- ddply( df, "group1", function(x) 
                     data.frame( meanValue = mean(x$values) ) )
df <- merge( df, group1Mean )
df

这是可行的,但是否有其他方法可以提高可读性、性能等?

一行代码就可以做到这一点:

new <- ddply( df, "group1", transform, numcolwise(mean))
new

group1 group2      values    meanValue
1       1      A  0.48742905 -0.121033381
2       1      A -0.04493361 -0.121033381
3       1      C -0.62124058 -0.121033381
4       1      C -0.30538839 -0.121033381
5       2      A  1.51178117  0.004803931
6       2      B  0.73832471  0.004803931
7       2      A -0.01619026  0.004803931
8       2      B -2.21469989  0.004803931
9       3      B  1.12493092  0.758597929
10      3      C  0.38984324  0.758597929
11      3      B  0.57578135  0.758597929
12      3      A  0.94383621  0.758597929

identical(df, new)
[1] TRUE

new您不能将
x
添加到传递给
ddply
的函数中吗

df <- ddply( df, "group1", function(x)
             data.frame( x, meanValue = mean(x$values) ) )
df我认为
ave()
在这里比您展示的plyr调用更有用(我对plyr不够熟悉,不知道您是否可以直接使用plyr做您想做的事情,如果您不能做,我会感到惊讶!)或其他基本R替代方案(
aggregate()
tapply()
):

您可以使用
in()
transform()
将此结果直接嵌入
df

> df2 <- within(df, meanValue <- ave(values, group1, FUN = mean))
> head(df2)
  group1 group2     values    meanValue
1      1      A  0.4874291 -0.121033381
2      2      B  0.7383247  0.004803931
3      3      B  0.5757814  0.758597929
4      1      C -0.3053884 -0.121033381
5      2      A  1.5117812  0.004803931
6      3      C  0.3898432  0.758597929
> df3 <- transform(df, meanValue = ave(values, group1, FUN = mean))
> all.equal(df2,df3)
[1] TRUE

在性能方面,您可以使用内置聚合的包来执行类似的操作,由于索引和基于C的实现,该包速度非常快。例如,您的示例中已经存在给定的
df

A
dplyr
可能性:

library(dplyr)
df %>% 
  group_by(group1) %>%
  mutate(meanValue = mean(values))

这将按原始顺序返回数据帧。如果您希望按“组1”订购,请将
arrange(group1)
添加到管道中。

请参见我忘记了所有有关
transform的内容。事后看来很明显。但是谢谢你解释我不熟悉的
numcolwise
。这是一个很好的习惯用法,但是当一些变量应该是和,而另一些则意味着时,这很难做到。@richiemorrisroe比其他习惯用法更难吗?@Andrie不,我只是希望你能用一些我没有意识到的显而易见的解决方案来回答。漂亮。我没有意识到其他函数可以与
ave()
一起使用。。。很明显,我以前应该读过这些文件。
> df2 <- within(df, meanValue <- ave(values, group1, FUN = mean))
> head(df2)
  group1 group2     values    meanValue
1      1      A  0.4874291 -0.121033381
2      2      B  0.7383247  0.004803931
3      3      B  0.5757814  0.758597929
4      1      C -0.3053884 -0.121033381
5      2      A  1.5117812  0.004803931
6      3      C  0.3898432  0.758597929
> df3 <- transform(df, meanValue = ave(values, group1, FUN = mean))
> all.equal(df2,df3)
[1] TRUE
> head(df2[order(df2$group1, df2$group2), ])
   group1 group2      values    meanValue
1       1      A  0.48742905 -0.121033381
10      1      A -0.04493361 -0.121033381
4       1      C -0.30538839 -0.121033381
7       1      C -0.62124058 -0.121033381
5       2      A  1.51178117  0.004803931
11      2      A -0.01619026  0.004803931
library("data.table") dt<-as.data.table(df) setkey(dt,group1) dt<-dt[,list(group2,values,meanValue=mean(values)),by=group1] dt group1 group2 values meanValue [1,] 1 A 0.82122120 0.18810771 [2,] 1 C 0.78213630 0.18810771 [3,] 1 C 0.61982575 0.18810771 [4,] 1 A -1.47075238 0.18810771 [5,] 2 B 0.59390132 0.03354688 [6,] 2 A 0.07456498 0.03354688 [7,] 2 B -0.05612874 0.03354688 [8,] 2 A -0.47815006 0.03354688 [9,] 3 B 0.91897737 -0.20205707 [10,] 3 C -1.98935170 -0.20205707 [11,] 3 B -0.15579551 -0.20205707 [12,] 3 A 0.41794156 -0.20205707

dt <- as.data.table(df)
dt[, meanValue := mean(values), by = group1]
library(dplyr)
df %>% 
  group_by(group1) %>%
  mutate(meanValue = mean(values))