如何在不同大小的几个数据框中平均元素?

时间:2015-02-02 08:31:06

标签: r dataframe average reduce

我有一系列具有相同结构(相同列数)的文本文件(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)

当所有数据帧具有相同的大小时,这可以很好地退出。但是当我在几个数据框中有更多行时,我得到了这个错误:

  

Ops.data.frame中的错误(init,x [[i]]):'+'仅定义为   同等大小的数据框

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

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

文件1:

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

file2的:

           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

提前致谢

2 个答案:

答案 0 :(得分:3)

以下解决方案使用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将填充零值,从而产生不同的行平均值。

答案 1 :(得分:2)

我们可以使用rbindlist中的data.table来“rbind”列表元素(list(x,y))。 id.col=TRUE为每个列表元素生成id。创建按“.id”分组的序列索引(.idx),使用“.idx”作为分组变量,并使用.SD获取数据表子集(lapply)的方法。 .SDcols指定要为“均值”计算选择的列。

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

UPDATE2

base R选项是创建列表元素具有相同维度的列表(“lst1”)。这可以通过首先从检查“lst”(NA)的维度创建尺寸等于“最大”nrow / ncol的Dim1 <- sapply(..)数据集“d1”来完成。使用Map填充与每个“lst”元素的“rownames / colnames”匹配的“d1”元素。输出“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)