如何对大小不等的多个数据框中的元素进行平均?

How to average elements in several data frames with unequal size?

我有一系列具有相同结构(相同列数)的文本文件(100 个文件),需要对所有文件中的每个元素进行平均。我使用的是这段代码:

my.list<-list()
for(j in 1:100){
  my.list[[j]]<-read.table(paste('file_',j,'.txt',sep='')
                               ,header=TRUE)
}

all=Reduce("+", my.list) / length(my.list)

当所有数据框都具有相同的大小时,这可以正常工作。但是当我在几个数据框中有更多行时,我得到这个错误:

Error in Ops.data.frame(init, x[[i]]) : ‘+’ only defined for equally-sized data frames

我想知道是否有任何解决方案可以对所有数据框中未显示的行的现有数量求平均值。

这是包含 1 列的示例文件(我只放了两个文件,但在我的数据中有 100 个文件):

文件 1:

             x
1 3
2 5
3 1
4 8
5 2
6 6
7 0

文件 2:

           x
1 4
2 2
3 6
4 1
5 9
6 2

我想要一个输出:

          x
1 3.5
2 3.5
3 3.5
4 4.5
5 5.5
6 4
7 0

提前致谢

我们可以使用 rbindlistdata.table 到 "rbind" 列表元素 (list(x,y))。 id.col=TRUE 为每个列表元素生成 id。创建一个按“.id”分组的序列索引(.idx),使用“.idx”作为分组变量并使用lapply获取数据表(.SD)子集的均值。 .SDcols 将列指定为 select 以进行 "mean" 计算。

library(data.table) # data.table_1.9.5 
rbindlist(list(x,y), idcol=TRUE)[,.idx:=1:.N , by = .id][, 
                  lapply(.SD, mean), .SDcols=2:3, by= .idx]
#    .idx Col1 Col2
#1:    1    1  3.5
#2:    2    2  3.5
#3:    3    3  3.5
#4:    4    4  4.5
#5:    5    5  5.5
#6:    6    6  4.0
#7:    7    7  0.0

或者我们可以使用@David Arenburg 建议的另一个选项。除了使用 colMeans 而不是 lapply(.SD,.

外,步骤与上述相同
rbindlist(list(x,y), idcol=TRUE)[, .idx:=1:.N, by =.id][,
              as.list(colMeans(.SD)), .SDcols=2:3, by = .idx]

更新

假设如果数据集有来自多个数据集的变量 ncols,我们可以使用 fread 从工作目录读取所有文件,使用 rbindlistfill=TRUE,并使用上面的代码并在 .SDcols

中进行适当的更改
  files <- list.files() 
  lst <- lapply(files, fread)
  rbindlist(lst, idcol=TRUE, fill=TRUE)[, .idx:=1:.N, by =.id][,
              as.list(colMeans(.SD, na.rm=TRUE)), .SDcols=2:3, by = .idx]

举个例子

  lst <- list(x,y,z)
  rbindlist(lst, idcol=TRUE, fill=TRUE)[, 
     .idx:=1:.N, by=.id][, as.list(colMeans(.SD, na.rm=TRUE)),
               .SDcols=2:4, by=.idx][,-1, with=FALSE]
  #    Col1     Col2 Col3
  #1:    1 3.000000    3
  #2:    2 3.333333    4
  #3:    3 3.666667    5
  #4:    4 4.666667    6
  #5:    5 5.666667    7
  #6:    6 4.000000  NaN
  #7:    7 0.000000  NaN

更新2

base R 选项将创建一个列表 ("lst1"),其中列表元素具有相同的维度。这可以通过首先创建一个 NA 数据集 "d1" 来完成,其维度等于 "maximum" nrow/ncol 检查 "lst" (Dim1 <- sapply(..)) 的维度.使用 Map 填充 "d1" 中与每个 "lst" 元素的 "rownames/colnames" 匹配的元素。输出"lst1"可以转换为数组(ar1),使用apply带边距(c(1,2))得到mean值。

   Dim1 <- sapply(lst, dim)
   d1 <- as.data.frame(matrix(NA, ncol=max(Dim1[2,]), 
                              nrow=max(Dim1[1,])))
   nm1 <- unique(unlist(sapply(lst, colnames)))
   names(d1) <- nm1
   lst1 <-Map(function(x,y) {
      y[match(row.names(x), row.names(y)),
                  match(colnames(x), colnames(y))] <- x
       y }, 
       lst, list(d1))

 ar1 <- array(unlist(lst1), dim=c(max(Dim1[1,]), max(Dim1[2,]), length(lst1)))
 apply(ar1, c(1,2), mean, na.rm=TRUE)
 #      [,1]     [,2] [,3]
 #[1,]    1 3.000000    3
 #[2,]    2 3.333333    4
 #[3,]    3 3.666667    5
 #[4,]    4 4.666667    6
 #[5,]    5 5.666667    7
 #[6,]    6 4.000000  NaN
 #[7,]    7 0.000000  NaN

数据

x <- structure(list(Col1 = 1:7, Col2 = c(3L, 5L, 1L, 8L, 2L, 6L, 0L
)), .Names = c("Col1", "Col2"), class = "data.frame", row.names = 
c(NA, -7L))

y <- structure(list(Col1 = 1:6, Col2 = c(4L, 2L, 6L, 1L, 9L, 2L)), 
.Names = c("Col1", "Col2"), class = "data.frame", row.names = c(NA, 
-6L))

z <- data.frame(Col1=1:5, Col2=2:6, Col3=3:7)

以下解决方案使用了 zoo 包

install.packages("zoo")
library(zoo)

两个不等向量

file1<-c(3,5,1,8,2,6,0)
file2<-c(4,2,6,1,9,2)

z1<-zoo(file1)
z2<-zoo(file2)

dat<-cbind(z1,z2)

rowMeans(dat, na.rm=TRUE)

对于超过 2 个向量:

file3<-c(2,3)
z3<-zoo(file3)
dat<-cbind(z1,z2,z3)

rowMeans(dat, na.rm=TRUE)

不等矩阵

z1<-zoo(cbind(c(1,2,3),c(0,2,7)))
z2<-zoo(cbind(c(0,3,4,7,2),c(1,4,2,3,8)))

dat<-cbind(z1,z2)
rowMeans(dat, na.rm=TRUE)

注意: 在提供的示例中,缺少的元素用 NA 填充。如果您使用 cbind(z1,z2,fill=0),NA 将填充零值,从而产生不同的行平均值。