列中每组的平均值,每行的结果

Mean per group in a column, result per row

我有这个数据框(根据@Vinterwoo 的代码调整),我正在寻找一个函数来获取每列的每组平均值。因此,C1 和 C2 列中 A 组的平均值,以及 B 组等的平均值。我知道如何获得每组的平均值(例如使用 aggregate),但我需要在相应组的每一行中显示平均值(请参阅所需的输出)。

C1 <- c(3,2,4,3,6,7,5)
C2 <- c(3,7,3,4,5,2,1)
DF <- data.frame(ID=c("A","C","A","C","E","F","E"),C1=C1,C2=C2)

ID C1 C2
A  3  3
C  2  7
A  4  3
C  3  4
E  6  5
F  7  2
E  5  1

期望的输出:

ID C1 C2 avg.C1 avg.C2
A  3  3    3.5    3.0
C  2  7    2.5    5.5
A  4  3    3.5    3.0
C  3  4    2.5    5.5
E  6  5    5.5    3.0
F  7  2    7.0    2.0
E  5  1    5.5    3.0

尝试:

library(dplyr)
DF %>% group_by(ID) %>% mutate(avg.C1 = mean(C1), avg.C2 = mean(C2))

给出:

#Source: local data frame [7 x 5]
#Groups: ID
#
#  ID C1 C2 avg.C1 avg.C2
#1  A  3  3    3.5    3.0
#2  C  2  7    2.5    5.5
#3  A  4  3    3.5    3.0
#4  C  3  4    2.5    5.5
#5  E  6  5    5.5    3.0
#6  F  7  2    7.0    2.0
#7  E  5  1    5.5    3.0

如果您要使用 base 创建一个新列,您可以简单地计算所需的值并将它们分配给列。要计算它,请取 ID 等于其自身的每个 C 的平均值:

DF$avg.C1 <- sapply(1:nrow(DF), function(i) mean(DF$C1[DF$ID==DF$ID[i]]))
DF$avg.C2 <- sapply(1:nrow(DF), function(i) mean(DF$C2[DF$ID==DF$ID[i]]))

您可以像下面这样使用聚合和合并

DF2=aggregate(cbind(C1, C2) ~ ID , data= DF , FUN= mean)
DF_Wanted= merge(DF, DF2, by=c("ID"), all=TRUE)

我建议使用 "data.table" 软件包:

sdcols <- names(DF)[-1]      ## A vector of the new columns we want to add
as.data.table(DF)[, paste(sdcols, "mean", sep = "_") := lapply(.SD, mean), 
                  by = ID][] ## you can also be more specific and specify sdcols
#    ID C1 C2 C1_mean C2_mean
# 1:  A  3  3     3.5     3.0
# 2:  C  2  7     2.5     5.5
# 3:  A  4  3     3.5     3.0
# 4:  C  3  4     2.5     5.5
# 5:  E  6  5     5.5     3.0
# 6:  F  7  2     7.0     2.0
# 7:  E  5  1     5.5     3.0

如注释代码中所示,您可以使用 .SDcols 参数指定要作用于哪些列:

sdcols <- names(DF)[-1]
as.data.table(DF)[, paste(sdcols, "mean", sep = "_") := lapply(.SD, mean), 
                  by = ID, .SDcols = sdcols][]

已经发布了一些很好的答案,但令我惊讶的是没有人提到 ave(),它基本上就是为此目的而设计的;它甚至可以在没有任何刺激的情况下运行 mean()

cbind(DF,avg.C1=ave(DF$C1,DF$ID),avg.C2=ave(DF$C2,DF$ID));
##   ID C1 C2 avg.C1 avg.C2
## 1  A  3  3    3.5    3.0
## 2  C  2  7    2.5    5.5
## 3  A  4  3    3.5    3.0
## 4  C  3  4    2.5    5.5
## 5  E  6  5    5.5    3.0
## 6  F  7  2    7.0    2.0
## 7  E  5  1    5.5    3.0