【问题标题】:R weighted arithmetic meanR加权算术平均值
【发布时间】:2014-05-06 18:52:52
【问题描述】:

假设我在 R 中有这个 data.frame:

ages <- data.frame(Indiv = numeric(),
    Age = numeric(),
    W = numeric())
ages[1,] <- c(1,10,2)
ages[2,] <- c(1,15,5)
ages[3,] <- c(2,5,1)
ages[4,] <- c(2,100,2)

ages

  Indiv Age W
1     1  10 2
2     1  15 5
3     2   5 1
4     2 100 2

如果我这样做:

meanAge <- aggregate(ages$Age,list(ages$Indiv),mean)

我得到每个 Indiv (Group.1) 的平均年龄 (x):

  Group.1    x
1       1 12.5
2       2 52.5

但我想计算年龄的加权算术平均值(体重为 W)。如果我这样做:

WmeanAge <- aggregate(ages$Age,list(ages$Indiv),weighted.mean,ages$W)

我明白了:

Error in weighted.mean.default(X[[1L]], ...) : 
  'x' and 'w' must have the same length

我想我应该有:

  Group.1           x
1       1 13.57142857
2       2 68.33333333

我做错了什么?提前致谢!

【问题讨论】:

    标签: r aggregate weighted-average


    【解决方案1】:

    Doh,你打败了我。但无论如何,这是我同时使用plyrdplyr 的答案:

    ages = data.frame(Indiv = c(1,1,2,2),
                  Age = c(10,15,5,100),
                  W = c(2,5,1,2))
    
    library(plyr)
    ddply(ages, .(Indiv), summarize, 
          mean = mean(Age),
          wmean = weighted.mean(Age, w=W))
    
    
    library(dplyr)
    ages %.% 
      group_by(Indiv) %.% 
      summarise(mean = mean(Age), wmean = weighted.mean(Age, W))
    

    【讨论】:

    • 非常好的答案 - 特别是说明为什么 dplyr 对于大多数用途来说更容易
    【解决方案2】:

    如果你想使用基函数,这里有一种可能性

    as.vector(by(ages[c("Age","W")],
        list(ages$Indiv),
         function(x) {
             do.call(weighted.mean, unname(x))
         }
    ))
    

    由于聚合不会对多个列进行子集化,我使用更通用的by 并将结果简化为向量。

    【讨论】:

      【解决方案3】:

      问题在于 aggregate 没有拆分 w 参数 - 因此 weighted.mean 正在接收 ages$Age 的子集,但它没有接收到 ages$W 的等效子集。

      试试plyr 包!!这很棒。我在编写的 95% 的脚本中都使用了它。

      library("plyr")
      
      # the plyr package has functions that come in the format of  _ _ ply
      # the first blank is the input format, and the second is the output format
      # d = data.frame, l = list, a = array, etc.
      # thus, with ddply(), you supply a data.frame (ages), and it returns a data.frame (WmeanAge)
      
      # .data is your data set
      # .variables is the name of the column (or columns!) to be used to split .data
      # .fun is the function you want to apply to each subset of .data
      
      new.weighted.mean <- function(x, ...){
         weighted.mean(x=x[,"Age"], w=x[,"W"], ...)
      }
      
      WmeanAge <- ddply(.data=ages, .variables="Indiv", .fun=new.weighted.mean, na.rm=TRUE)
      print(WmeanAge)
      

      【讨论】:

      • 我在这里看到了这个包:stackoverflow.com/a/10407563/1086511。但是聚合函数可以选择使用具有多个参数的函数。你是在告诉我它不能用 weighted.mean 做吗?使用一个包来做一些基本功能应该做的事情,这违背了我的设计理念......
      • @Rodrigo 你绝对可以提供额外的参数!问题是这些参数不会被聚合等子集化,就像你的数据被子集化一样。如果您希望以相同方式对多个参数进行子集化,请将这些参数作为 data.frame 提供,并调整函数以查看右列(作为一种解决方案)。
      • 如果您将此解释为答案并且有效,我会选择它。谢谢,@rbatt!
      • @Rodrigo 我(希望)对我的答案进行了一些有用的编辑——有一个新函数可以知道您提供的 data.frame 中的哪些列包含 x 和 w,我使用 ... 来允许将附加参数传递给函数的选项。在这种情况下,我使用 na.rm=TRUE 来展示如何通过 ddply 设置此参数。
      【解决方案4】:

      您的权重值数量与您的组数不匹配,因此聚合无法正确折叠组。这是一个使用 for 循环的非常不雅的解决方案。

      ages = data.frame(Indiv=c(1,1,2,2),Age=c(10,15,5,100),W=c(2,5,1,2))
      
      age.Indiv <- vector()
        for(i in unique(ages$Indiv)){
        age.Indiv <- append(age.Indiv, weighted.mean( ages[ages$Indiv == i ,]$Age, 
                            ages[ages$Indiv == i ,]$W))
          } 
        names(age.Indiv) <- unique(ages$Indiv)
          age.Indiv
      

      【讨论】:

      • 这不是真的。唯一值的长度不是问题。问题是聚合不会像子集第一个参数一样子集传递给它的其他参数。
      • 但是同一组有多个权重是没有意义的。这些函数的行为似乎符合预期。
      • 我认为您在决定什么是“有意义的”方面给予了这些功能太多的功劳。 weighted.mean 应该能够计算加权平均值,无论您传递什么两个向量,只要它们的长度相同。这里的问题是它们与aggregate() 处理... 参数的方式不同。
      • @MrFlick,这是真的,我在 base 中提供了一个不同的,尽管不优雅的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2021-09-15
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多