【问题标题】:Calculate means from different data frames从不同的数据帧计算均值
【发布时间】:2017-05-29 21:46:21
【问题描述】:

我的目标是计算最终的数据框,其中包含来自多个不同数据框的平均值。给定这样的数据:

A <- c(1,2,3,4,5,6,7,8,9)
B <- c(2,2,2,3,4,5,6,7,8)
C <- c(1,1,1,1,1,1,2,2,1)
D <- c(5,5,5,5,6,6,6,7,7)
E <- c(4,4,3,5,6,7,8,9,7)

DF1 <- data.frame(A,B,C)
DF2 <- data.frame(E,D,C)
DF3 <- data.frame(A,C,E)
DF4 <- data.frame(A,D,E)

我想计算每个数据框中所有三列(每行)的平均值。为此,我组合了一个 for 循环:

All <- data.frame(matrix(ncol = 3, nrow = 9))
for(i in seq(1:ncol(DF1))){
    All[,i] <- mean(c(DF1[,i], DF2[,i], DF3[,i], DF4[,i]))
}

        X1       X2       X3
1 5.222222 4.277778 3.555556
2 5.222222 4.277778 3.555556
3 5.222222 4.277778 3.555556
4 5.222222 4.277778 3.555556
5 5.222222 4.277778 3.555556
6 5.222222 4.277778 3.555556
7 5.222222 4.277778 3.555556
8 5.222222 4.277778 3.555556
9 5.222222 4.277778 3.555556

但最终结果是我计算了整个列的平均值(而不是每一行的平均值)。

例如,4 个数据帧的第一行和第一列是 1,4,1,1。所以我希望最终数据帧的第一列和第一行是 1.75 (mean(c(1,4,1,1))

【问题讨论】:

  • apply(abind::abind(DF1, DF2, DF3, DF4, along = 3), 1:2, mean)

标签: r dataframe mean


【解决方案1】:

我们将数据集放在list中,使用Reduce得到对应元素的总和(+),然后除以数据集的数量

Reduce(`+`, mget(paste0("DF", 1:4)))/4
#     A    B   C
#1 1.75 3.25 2.5
#2 2.50 3.25 2.5
#3 3.00 3.25 2.0
#4 4.25 3.50 3.0
#5 5.25 4.25 3.5
#6 6.25 4.50 4.0
#7 7.25 5.00 5.0
#8 8.25 5.75 5.5
#9 8.50 5.75 4.0

注意:它应该比任何基于 apply 的解决方案都要快,并且输出是 data.frame 与原始数据集一样


如果我们想要tidyverse,那么另一种选择是

library(dplyr)
library(tidyr)
library(purrr)
library(tibble)
mget(paste0("DF", 1:4)) %>%
        map(rownames_to_column, "rn") %>% 
        map(setNames, c("rn", LETTERS[1:3])) %>%
        bind_rows() %>% 
        group_by(rn) %>%
        summarise_each(funs(mean))
# A tibble: 9 × 4
#     rn     A     B     C
#  <chr> <dbl> <dbl> <dbl>
#1     1  1.75  3.25   2.5
#2     2  2.50  3.25   2.5
#3     3  3.00  3.25   2.0
#4     4  4.25  3.50   3.0
#5     5  5.25  4.25   3.5
#6     6  6.25  4.50   4.0
#7     7  7.25  5.00   5.0
#8     8  8.25  5.75   5.5
#9     9  8.50  5.75   4.0

【讨论】:

  • vectorized 是什么意思? Reduce 只是 for 循环的包装器(如 apply)。
  • @nicola 根据我的经验,Reduce 似乎比apply
  • 不要认为你的经验可以定义什么是矢量化的,什么不是。 Reduceapply 都包裹 for 循环。不知道如何比较它们,因为它们做不同的事情。
【解决方案2】:

由于您所描述的实际上是一个数组,因此您实际上可以将其与abind::abind 合并,这使得操作非常简单:

apply(abind::abind(DF1, DF2, DF3, DF4, along = 3), 1:2, mean)
##          A    D   E
##  [1,] 1.75 3.25 2.5
##  [2,] 2.50 3.25 2.5
##  [3,] 3.00 3.25 2.0
##  [4,] 4.25 3.50 3.0
##  [5,] 5.25 4.25 3.5
##  [6,] 6.25 4.50 4.0
##  [7,] 7.25 5.00 5.0
##  [8,] 8.25 5.75 5.5
##  [9,] 8.50 5.75 4.0

列名无意义,结果是一个矩阵,不是data.frame,不过就算你用data.frame包起来,还是很快的。

【讨论】:

  • 作为 alt.. rowMeans(abind::abind(DF1, DF2, DF3, DF4, along = 3), dims=2)
  • 很好,我不知道那个参数!不过,它的编号有点奇怪。
  • ha..yup.. 每隔一段时间,我几乎都能得到暗淡的理性,但它永远不会坚持下去。没有帮助 colMeans 的工作方式有点不同。
【解决方案3】:

tidyversebase 的组合:

#install.packages('tidyverse')

library(tidyverse)


transpose(list(DF1, DF2, DF3, DF4)) %>%
  map(function(x) 
    rowMeans(do.call(rbind.data.frame, 
                     transpose(x)))) %>%
  bind_cols()

应该让步:

#       A     B     C
#   <dbl> <dbl> <dbl>
# 1  1.75  3.25   2.5
# 2  2.50  3.25   2.5
# 3  3.00  3.25   2.0
# 4  4.25  3.50   3.0
# 5  5.25  4.25   3.5
# 6  6.25  4.50   4.0
# 7  7.25  5.00   5.0
# 8  8.25  5.75   5.5
# 9  8.50  5.75   4.0

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多