【问题标题】:How to calculate the mean of those columns in a data frame with the same column name如何计算具有相同列名的数据框中这些列的平均值
【发布时间】:2014-05-22 19:37:33
【问题描述】:

我有一个数据框,其中包含 66 个变量的 10299 个观察值。其中一些变量共享一个共同的列名,我想为每个观察计算这些变量的平均值。

具有以下矩阵,列名c(A, B, C, B, A ,C)

A B C B A C                             
1 2 3 4 5 6         
3 5 6 7 4 3                             
3 3 3 3 5 5                             
2 2 2 2 2 2

我想得到:

A   B   C    
3   3   4.5
3.5 6   4.5
4   3   4
2   2   2

我尝试了 for 循环,命令 aggregate() 但我没有得到想要的结果。

对不起,如果这个问题看起来太简单了,我已经在谷歌上搜索过可能的解决方案,但我没有找到任何解决方案。

【问题讨论】:

标签: r


【解决方案1】:

这里有一个解决方案。

首先让我们定义一个示例性的 data.frame(与您的示例相同)。

df <- as.data.frame(
    matrix(c(1,3,3,2,2,5,3,2,3,6,3,2,4,7,3,2,5,4,5,2,6,3,5,2),
        ncol=6,
        dimnames=list(NULL, c("A", "B", "C", "B", "A", "C"))
    )
  )

下面我们对每个唯一的列名col应用自定义函数: 它选择所有名为col 的列并计算rowMeans。结果,原子向量列表,将被强制转换为 data.frame:

res <- as.data.frame( # sapply returns a list here, so we convert it to a data.frame
    sapply(unique(names(df)), # for each unique column name
       function(col) rowMeans(df[names(df) == col]) # calculate row means
    )
  )

结果:

res
##     A B   C
## 1 3.0 3 4.5
## 2 3.5 6 4.5
## 3 4.0 3 4.0
## 4 2.0 2 2.0

编辑: 由于已经提出了许多解决方案,让我们对它们进行基准测试:

set.seed(123)
df <- as.data.frame(matrix(sample(1:9, replace=TRUE, 10000*100),
   dimnames=list(NULL, sample(LETTERS[1:5], 100, replace=TRUE)), ncol=100))
library(microbenchmark)
microbenchmark(...)
## Unit: milliseconds
##                   min         lq     median         uq        max neval
## @gagolews   61.196075   65.73211   77.22533  119.42028  127.32557    10
## @joran       8.297964   10.05242   10.90564   15.25943   65.69156    10
## @Davide   5535.272680 5731.24220 5754.67006 5808.47807 5862.22628    10

明显的赢家(至少就速度而言)是@joran 的lapply+split+Reduce。恭喜! :-)

【讨论】:

  • 您的解决方案保留了行名,而 joran 删除了它们(很容易在最后重新分配,但为了公平起见,重新分配它们所花费的时间应该在基准范围内)。 (Davide 的解决方案也维护行名。)
【解决方案2】:

使用applytapply 的组合:

t(apply(df, 1, function(x) tapply(x, colnames(df), mean)))

#        A B   C
# [1,] 3.0 3 4.5
# [2,] 3.5 6 4.5
# [3,] 4.0 3 4.0
# [4,] 2.0 2 2.0

【讨论】:

  • 很聪明。非常感谢。
【解决方案3】:

您可以使用split.default 根据列名将数据框划分为不同的组,然后使用rowMeans 获取同名列的平均值。

sapply(split.default(df, names(df)), rowMeans)
#       A B   C
#[1,] 3.0 3 4.5
#[2,] 3.5 6 4.5
#[3,] 4.0 3 4.0
#[4,] 2.0 2 2.0

数据

df = structure(list(A = c(1L, 3L, 3L, 2L), B = c(2L, 5L, 3L, 2L), 
    C = c(3L, 6L, 3L, 2L), B = c(4L, 7L, 3L, 2L), A = c(5L, 4L, 
    5L, 2L), C = c(6L, 3L, 5L, 2L)), .Names = c("A", "B", "C", 
"B", "A", "C"), class = "data.frame", row.names = c(NA, -4L))

【讨论】:

    【解决方案4】:

    在我看来,这可行,但不如 gegolews 解决方案好:

    x <- read.table(text = "A B C B A C                             
     1 2 3 4 5 6         
     3 5 6 7 4 3                             
     3 3 3 3 5 5                             
     2 2 2 2 2 2",header = TRUE,sep = "",check.names = FALSE)
    
    as.data.frame(lapply(split(as.list(x),f = colnames(x)),function(x) Reduce(`+`,x) / length(x)))
    ##    A B   C
    ##1 3.0 3 4.5
    ##2 3.5 6 4.5
    ##3 4.0 3 4.0
    ##4 2.0 2 2.0
    

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 2016-03-03
      • 2021-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多