【问题标题】:Display weighted mean by group in the data.frame在 data.frame 中按组显示加权平均值
【发布时间】:2016-11-25 08:03:37
【问题描述】:

关于命令byweighted.mean 的问题已经存在,但没有一个能够帮助解决我的问题。我是 R 新手,我更习惯于数据挖掘语言而不是编程。

我有一个数据框,其中包含每个人(观察/行)的收入、教育水平和样本权重。我想按教育水平计算收入的加权平均值,并且我希望将结果与原始数据框的新列中的每个人相关联,如下所示:

obs income education weight incomegroup
1.   1000      A       10    --> display weighted mean of income for education level A
2.   2000      B        1    --> display weighted mean of income for education level B
3.   1500      B        5    --> display weighted mean of income for education level B
4.   2000      A        2    --> display weighted mean of income for education level A

我试过了:

data$incomegroup=by(data$education, function(x) weighted.mean(data$income, data$weight))    

它不起作用。加权平均值以某种方式计算并出现在“收入组”列中,但对于整个集合而不是按组或仅针对一个组,我不知道。我阅读了有关包裹 plyraggregate 的内容,但它似乎没有做我感兴趣的事情。

ave{stats} 命令给出了我正在寻找的东西,但只是简单的意思:

data$incomegroup=ave(data$income,data$education,FUN = mean)

它不能与权重一起使用。

提前感谢您的帮助!

【问题讨论】:

    标签: r weighted-average


    【解决方案1】:

    在基础 R 中有一个函数 weighted.mean。不幸的是,它不适用于 ave。一种解决方案是使用data.table

    library(data.table)
    setDT(data)
    data[, incomeGroup := weighted.mean(income, weight), by=education]
    data
       income education weight incomeGroup
    1:   1000         A     10    1166.667
    2:   2000         B      1    1583.333
    3:   1500         B      5    1583.333
    4:   2000         A      2    1166.667
    

    一种适用于ave 的奇怪方法是

    ave(df[c("income", "weight")], df$education,
        FUN=function(x) weighted.mean(x$income, x$weight))[[1]]
    [1] 1166.667 1583.333 1583.333 1166.667
    

    您将子集 data.frame 提供给函数,然后按您的分组变量进行分组。 FUN 参数创建一个函数,该函数接受一个 data.frame 并将weighted.mean 应用于结果。由于最终输出是一个 data.frame,[[1]] 返回一个带有所需结果的向量。

    请注意,这只是证明这是可能的——我不推荐这种方法,data.table 技术更简洁,并且在大于 1000 次观察的数据集上速度更快。

    【讨论】:

      【解决方案2】:

      如果我们使用mutate,那么我们可以避免left_join

      library(dplyr)
      df %>%
         group_by(education) %>% 
         mutate(weighted_income = weighted.mean(income, weight))
      #    obs income education weight weighted_income
      #  <int>  <int>    <fctr>  <int>           <dbl>
      #1     1   1000         A     10        1166.667
      #2     2   2000         B      1        1583.333
      #3     3   1500         B      5        1583.333
      #4     4   2000         A      2        1166.667
      

      【讨论】:

      • 建议的 3 个解决方案有效。然而,这个解决方案(使用库dplyrmutate)是最有效的。使用库data.table 也可以正常工作,但需要安装包并给出有关 R 版本的警告:在我使用 R 3.2.3 时使用 R 3.2.5 编译的包。谢谢大家的效率!
      • @Elixterra 尽管dplyr 中的akrun 代码看起来更易读,但data.table 方法的效率要高得多。我比较了 14kk data.frame 和 696k 唯一 ID 上的两种解决方案。结果是:dplyr = user: 49.78 system: 0.01 elapsed: 50.05data.table = user: 7.15 system: 0.00 elapsed: 7.17
      【解决方案3】:

      尝试使用 dplyr 包如下:

      df <- read.table(text = 'obs income education weight   
                                1   1000      A       10     
                                2   2000      B        1     
                                3   1500      B        5     
                                4   2000      A        2', 
                       header = TRUE)     
      
      library(dplyr)
      
      df_summary <- 
        df %>% 
        group_by(education) %>% 
        summarise(weighted_income = weighted.mean(income, weight))
      
      df_summary
      # education weighted_income
      #     A        1166.667
      #     B        1583.333
      
      df_final <- left_join(df, df_summary, by = 'education')
      
      df_final
      # obs income education weight weighted_income
      #  1   1000         A     10        1166.667
      #  2   2000         B      1        1583.333
      #  3   1500         B      5        1583.333
      #  4   2000         A      2        1166.667
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-18
        • 1970-01-01
        • 1970-01-01
        • 2021-11-08
        相关资源
        最近更新 更多