【问题标题】:R Given a list of same dimension data tables, produce a summary of the means of each cellR给定相同维度数据表的列表,生成每个单元格的平均值的摘要
【发布时间】:2016-11-23 07:50:33
【问题描述】:

我发现很难用语言表达我想要的东西,所以我会尝试通过一个例子来解释它。假设我重复了两次实验并有两个表:

[df1]   [df2]
 X Y     X Y
 2 3     4 1
 5 2     2 4

这些表存储在一个列表中(如果需要,列表可以包含两个以上的元素),我想要做的是创建列表中表中每个单元格的平均值(或者对于通用版本,将我选择的任何函数应用于单元格,即 mad、sd 等)

[df1]   [df2]         [dfMeans]
 X Y     X Y        X          Y
 2 3     4 1     mean(2,4) mean(3,1)
 5 2     2 4     mean(5,2) mean(2,4)

我的问题有一个代码解决方案,但由于这是在 R 中,所以很可能有一种更清洁的方式来做事:

df1 <- data.frame(X=c(2,3,4),Y=c(3,2,1))
df2 <- data.frame(X=c(5,1,3),Y=c(4,1,4))
df3 <- data.frame(X=c(2,7,4),Y=c(1,7,6))
dfList <- list(df1,df2,df3)

dfMeans <- data.frame(MeanX=c(NA,NA,NA),MeanY=c(NA,NA,NA))

for (rowIndex in 1:nrow(df1)) {
  for (colIndex in 1:ncol(df1)) {
    valuesAtCell <- c()
    for (tableIndex in 1:length(dfList)) {
      valuesAtCell <- c(valuesAtCell, dfList[[tableIndex]][rowIndex,colIndex])
    }
    dfMeans[rowIndex, colIndex] <- mean(valuesAtCell)
  }
}

print(dfMeans)

【问题讨论】:

  • 数据帧中的行顺序是否重要?
  • 我以后可以随时使用它们,所以没有必要
  • 我的意思是:平均值是否要按行应用于数据帧?
  • 在单元方面,列表中的每个数据框都是重复实验,因此:需要mean(c(dfList[[1]][1,1], dfList[[2]][1,1]) mean(c(dfList[[1]][i,j], dfList[[2]][i,j])

标签: r list dataframe data.table


【解决方案1】:

这是一个data.table 解决方案,其中平均值在数据帧中按行应用:

library(data.table)

dtList <- rbindlist(dfList, use.names = TRUE, idcol = TRUE)
dtList
   .id X Y
1:   1 2 3
2:   1 3 2
3:   1 4 1
4:   2 5 4
5:   2 1 1
6:   2 3 4
7:   3 2 1
8:   3 7 7
9:   3 4 6

dtList[, rn := 1:.N, by = .id][][, .(X = mean(X), Y = mean(Y)), by = rn]
   rn        X        Y
1:  1 3.000000 2.666667
2:  2 3.666667 3.333333
3:  3 3.666667 3.666667

您可以将mean 替换为另一个聚合函数,例如median。 .id 列编号每行的原始数据帧的来源。

编辑

解决方案可以扩展到任意个列(只要所有数据帧中的列名和列顺序相同):

cn <- colnames(df1)
cn
[1] "X" "Y"

dtList[, rn := 1:.N, by = .id][, lapply(.SD, mean), by = rn, .SDcols = cn][, rn := NULL][]
          X        Y
1: 3.000000 2.666667
2: 3.666667 3.333333
3: 3.666667 3.666667

列名取自原始数据框之一,这增加了解决方案的灵活性。 [, rn := NULL] 从结果中删除行号,[] 确保打印结果。

【讨论】:

  • 最后一行,你为什么不能直接dtList[, .(X = mean(X), Y = mean(Y)), by = .id]?
  • @RichieCotton OP 想要计算数据帧中的单元格平均值。因此,平均值是逐行分别计算的。
  • 也许,另一种方法是重塑组合数据框。
  • 刚刚发现另一个问题,有什么方法可以处理任意数量的列,而不仅仅是X 和Y?即当您在代码运行之前不知道列数或它们的名称时
  • @AlexSpedding 我的答案中的扩展解决方案解决了任意数量的列的情况,其中列名仅在原始数据框中定义。
【解决方案2】:

您可以使用Reduce() 简单地将list 中的所有data.frame 相加,然后除以dfList 的长度,该长度等于它包含的df 的数量。

Reduce(`+`, dfList) / length(dfList)
#         X        Y
#1 3.000000 2.666667
#2 3.666667 3.333333
#3 3.666667 3.666667

【讨论】:

  • 谢谢,这适用于手段,但有没有办法用 + 代替函数名称,例如如果我想对数据应用更复杂的函数......类似:Reduce(FUNCTION_NAME, dfList)
  • Reduce() 的第一个参数始终是一个函数,在我们的例子中恰好是+。见?Reduce。
  • @mtoto。这对 any 函数not 起作用。简单地将+ 替换为mean 中的Reduce 将导致错误。
  • 我不确定Reduce 中使用的函数的标准是什么,但intersect 有效,但诸如mean sd 和mad 之类的函数不能
  • 根据?Reduce 适当的arity函数(Reduce的二进制,...是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2020-04-24
  • 1970-01-01
  • 2017-12-22
  • 2020-12-07
  • 1970-01-01
相关资源
最近更新 更多