【问题标题】:Mean of elements in a list of data.framesdata.frames 列表中元素的平均值
【发布时间】:2011-11-30 21:07:37
【问题描述】:

假设我有一个 data.frames 列表(相同的行和列)

dat1 <- as.data.frame(matrix(rnorm(25), ncol=5))
dat2 <- as.data.frame(matrix(rnorm(25), ncol=5))
dat3 <- as.data.frame(matrix(rnorm(25), ncol=5))

all.dat <- list(dat1=dat1, dat2=dat2, dat3=dat3)

如何返回单个 data.frame,它是列表中 data.frames 中每个元素的平均值(或总和等)(例如,列表 1、2 中第一行和第一列的平均值, 3等)?我在plyr 中尝试过lapplyldply,但它们返回列表中每个data.frame 的统计信息。

编辑:出于某种原因,这被重新标记为家庭作业。不管怎样,这并不重要,但这不是一个家庭作业问题。我只是不知道为什么我不能让它工作。感谢您的任何见解!

Edit2:进一步澄清: 我可以使用循环获得结果,但我希望有一种方法(一种更简单、更快的方法,因为我使用的数据有 12 行 x 100 列的 data.frames 并且有 1000+ 个列表数据帧)。

z <- matrix(0, nrow(all.dat$dat1), ncol(all.dat$dat1))

for(l in 1:nrow(all.dat$dat1)){
   for(m in 1:ncol(all.dat$dat1)){
      z[l, m] <- mean(unlist(lapply(all.dat, `[`, i =l, j = m)))
   }
}

用结果表示:

> z
        [,1]        [,2]        [,3]        [,4]       [,5]
[1,] -0.64185488  0.06220447 -0.02153806  0.83567173  0.3978507
[2,] -0.27953054 -0.19567085  0.45718399 -0.02823715  0.4932950
[3,]  0.40506666  0.95157856  1.00017954  0.57434125 -0.5969884
[4,]  0.71972821 -0.29190645  0.16257478 -0.08897047  0.9703909
[5,] -0.05570302  0.62045662  0.93427522 -0.55295824  0.7064439

我想知道是否有一种不那么笨重和更快的方法来做到这一点。谢谢!

【问题讨论】:

  • 那些不是手段。这些是中位数。
  • 感谢您指出这一点。

标签: r list dataframe plyr


【解决方案1】:

这是一个带有plyr 的单行。您可以将mean 替换为您想要的任何其他功能。

ans1 = aaply(laply(all.dat, as.matrix), c(2, 3), mean)

【讨论】:

  • 为什么是 c(2,3)?这是什么意思?
  • 这是一种访问数组的方法...它基本上将数据转换为 3 维数组,然后从中取出一列平均值...优雅 ...赞跨度>
【解决方案2】:

您可以更轻松地更改数据结构,将三个二维矩阵组合成一个 3 维数组(使用 abind 库)。然后解决方案更直接地使用apply 并指定要平均的维度。

编辑:

当我回答这个问题时,它被标记为homework,所以我只是给出了一个方法。最初的海报删除了那个标签,所以我会相信他/她的话不是。

library("abind")

all.matrix <- abind(all.dat, along=3)
apply(all.matrix, c(1,2), mean)

【讨论】:

  • 我不知道abind,我会调查一下。谢谢!
【解决方案3】:

我给出了一个答案,它使用完全不同的数据结构来实现结果。这个答案使用直接给出的数据结构(数据帧列表)。我认为它不太优雅,但还是想提供它。

Reduce(`+`, all.dat) / length(all.dat)

逻辑是将数据帧逐个元素添加在一起(+ 将处理数据帧),然后除以数据帧的数量。使用Reduce 是必要的,因为+ 一次只能接受两个参数(并且加法是关联的)。

【讨论】:

  • 这实际上是我最初尝试的一种策略,但这仅在我试图获得均值或总和时才有效,但我也希望可以选择找到中位数。我认为改变数据结构可能是我最好的选择。
  • 我想不出如何适应中位数;中位数一次需要所有元素,而均值可以一次建立两个。
  • 当data.frame的列表很长时,这个答案比stackoverflow.com/a/7651775/4907好。
  • 这是最干净的解决方案,但是当有字符列时它会失败(例如每个列表中的键相同)。
  • @jzadra 是的,但是字符串向量的“平均值”无论如何都没有很好地定义。在它们只是标签的地方,data.frame 可以是子集以删除它们,然后再添加一个集合。
【解决方案4】:

另一种只使用base函数来改变对象结构的方法:

listVec <- lapply(all.dat, c, recursive=TRUE)
m <- do.call(cbind, listVec)

现在您可以用rowMeans 计算mean 或用apply 计算median

means <- rowMeans(m)
medians <- apply(m, 1, median)

【讨论】:

    【解决方案5】:

    我会采取稍微不同的方法:

    library(plyr)
    tmp <- ldply(all.dat) # convert to df
    tmp$counter <- 1:5 # 1:12 for your actual situation
    ddply(tmp, .(counter), function(x) colMeans(x[2:ncol(x)]))
    

    【讨论】:

      【解决方案6】:

      您不能只使用嵌套的lapply() 调用吗?

      这似乎在我的机器上给出了正确的结果

      mean.dat <- lapply(all.dat, function (x) lapply(x, mean, na.rm=TRUE))
      

      【讨论】:

      • 使用此代码,您可以获得每个 data.frame 的列的平均值。您使用lapply(all.dat, colMeans) 获得相同的结果。
      猜你喜欢
      • 2020-07-12
      • 2021-09-30
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多