在R中重复行之间求平均值

12
我有一个数据框 df,其中行在名称列上是重复的,但在值列上不是:
name    value   etc1    etc2
A       9       1       X
A       10      1       X
A       11      1       X
B       2       1       Y
C       40      1       Y
C       50      1       Y

我需要将重复的名称合并到一行,并计算值列上的平均值。期望的输出如下:
name    value   etc1    etc2
A       10      1       X
B       2       1       Y
C       45      1       Y

我曾尝试使用df[duplicated(df$name),],但这并不能给出重复数据的平均值。我想使用aggregate(),但问题在于此函数的FUN部分也将应用于所有其他列,并且在计算字符内容时会遇到问题。由于所有其他列在“重复值”上具有相同的内容,因此我需要它们按原样聚合,就像名称列一样。有什么提示吗…?


1
你的其它列 etcX 是否也保证对于具有相同 name 的行是相同的? - Hong Ooi
@HongOoi 是的,我相信是这样的,我在之前的步骤中对它们进行了过滤以获取相似的内容。 - biohazard
@agstudy 抱歉,期望的输出已经包含在我的帖子中,但我忘记在句子中说明。这已被用户Metrics更正。 - biohazard
5个回答

15

这里是一个 data.table 的解决方案。该解决方案在一般情况下都适用,即使是有60列的数据框(data.frame)也可以使用。由于我按除了"value"之外的所有变量对数据进行分组(请参见下面我如何创建键),因此它可以工作。

library(data.table)
dat <- read.table(text='name    value   etc1    etc2
A       9       1       X
A       10      1       X
A       11      1       X
B       2       1       Y
C       40      1       Y
C       50      1       Y',header=TRUE)
keys <- colnames(dat)[!grepl('value',colnames(dat))]
X <- as.data.table(dat)
X[,list(mm= mean(value)),keys]
  name etc1 etc2 mm
1:    A    1    X 10
2:    B    1    Y  2
3:    C    1    Y 45

编辑:将扩展到多个变量。

如果您有多个数值变量需要计算平均值,例如,如果您的数据如下所示:

  name value etc1 etc2     value1
1    A     9    1    X  2.1763485
2    A    10    1    X -0.7954326
3    A    11    1    X -0.5839844
4    B     2    1    Y -0.5188709
5    C    40    1    Y -0.8300233
6    C    50    1    Y -0.7787496

上述解决方案可以像这样扩展:

X[,lapply(.SD,mean),keys]
   name etc1 etc2 value     value1
1:    A    1    X    10  0.2656438
2:    B    1    Y     2 -0.5188709
3:    C    1    Y    45 -0.8043865

这将计算所有不在keys列表中的变量的平均值。


12
你可以像下面这样使用aggregate()函数:
aggregate(df$value,by=list(name=df$name,etc1=df$etc1,etc2=df$etc2),data=df,FUN=mean)

1
在aggregate中不需要使用df$,因为它有一个数据参数,您可以在其中指定数据源(在本例中为df)。此外,aggregate还有一个公式接口,可能更容易阅读。 - talat

2

这段代码(由Metrics编写)几乎可以正常工作,只有一个地方出了问题(.name)。我稍微修改了一下:

sample<- structure(list(name = structure(c(1L, 1L, 1L, 2L, 3L, 3L), .Label = c("A", 
    "B", "C"), class = "factor"), value = c(9L, 10L, 11L, 2L, 40L, 
    50L), etc1 = c(1L, 1L, 1L, 1L, 1L, 1L), etc2 = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L), .Label = c("X", "Y"), class = "factor")), .Names = c("name", 
    "value", "etc1", "etc2"), class = "data.frame", row.names = c(NA, 
    -6L))

sample.m <- ddply(sample, 'name', summarize, value =mean(value), etc1=head(etc1,1), etc2=head(etc2,1))

sample.m
      name value etc1 etc2
    1    A    10    1    X
    2    B     2    1    Y
    3    C    45    1    Y

非常感谢!您是否知道是否有快捷方式可用,以便我不必输入所有其他列的名称?实际上,比我给出的示例中还要多得多。 - biohazard
@agstudy 我也不知道这个。谢谢你指出来。 - biohazard

1
假设您的数据框是df。
install.packages("plyr")
library(plyr)



df<- structure(list(name = structure(c(1L, 1L, 1L, 2L, 3L, 3L), .Label = c("A", 
    "B", "C"), class = "factor"), value = c(9L, 10L, 11L, 2L, 40L, 
    50L), etc1 = c(1L, 1L, 1L, 1L, 1L, 1L), etc2 = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L), .Label = c("X", "Y"), class = "factor")), .Names = c("name", 
    "value", "etc1", "etc2"), class = "data.frame", row.names = c(NA, 
    -6L))

df.m<-ddply(df,.(name),summarize, value=mean(value),etc1=head(etc1,1),etc2=head(etc2,1))

df.m
 name value etc1 etc2
1    A      10    1    X
2    B       2    1    Y
3    C      45    1    Y

非常感谢!不过有一个注意事项。在真实的数据集中,我有大约60个其他列,在重复时不会改变,应该保持不变,我需要一个一个地将它们作为ddply()的参数输入吗?还是有一种快捷技巧? - biohazard

0

这个简单的方法对我很有效:

avg_data <- aggregate( . ~ name, df, mean)

使用"aggregate"函数:应用公式方法(x ~ y)对所有变量(.)基于命名变量("name"),在数据框"df"内执行"mean"函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接