【问题标题】:Trimmed mean by group in R data.table在 R data.table 中按组修剪平均值
【发布时间】:2021-06-05 16:13:19
【问题描述】:

我有一个 data.table,我想在其上按月查找列 performance 的加权平均值。

  dat <- structure(list(year = c(2014, 2015, 2016, 2017, 2018, 2019, 2020, 
                                 2021, 2014, 2015, 2016, 2017, 2018, 2019, 2020), 
                        month = c(2, 
                                  2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10), 
                        performance = c(0.826973794097158, 
                                        0.61975709469356, 0.924350659523548, -0.183133219063708, -0.529913189565746, 
                                        -0.148531188902535, -0.0773058814083695, 1.42862504650241, 0.465498268732376, 
                                        0.148719963224136, 0.205614191281359, 0.560651497949418, -0.484408605607923, 
                                        0.875353374774486, 0.351469397380814)), 
                   row.names = c(NA, -15L), class = c("data.table", "data.frame"))

这个 data.table 如下所示 -

    year month performance
 1: 2014     2  0.82697379
 2: 2015     2  0.61975709
 3: 2016     2  0.92435066
 4: 2017     2 -0.18313322
 5: 2018     2 -0.52991319
 6: 2019     2 -0.14853119
 7: 2020     2 -0.07730588
 8: 2021     2  1.42862505
 9: 2014    10  0.46549827
10: 2015    10  0.14871996
11: 2016    10  0.20561419
12: 2017    10  0.56065150
13: 2018    10 -0.48440861
14: 2019    10  0.87535337
15: 2020    10  0.35146940

为了按月计算加权平均值,我使用了以下代码 -

setDT(dat)[, lapply(.SD, function(x) weighted.mean(x, na.rm = TRUE)), by = .(month), .SDcols = c("performance")]

我得到的结果是 -

   month performance
1:     2   0.3576029
2:    10   0.3032712

但是,月份 10 的加权平均表现应该大于月份 2,因为它具有更多的正值。

似乎只有 2021 年的 2 月份对其表现造成了严重影响,使其表现优于 10 月份的表现。 实际上,上面的代码只找到mean 而不是weighted.mean。如果我使用mean 而不是weighted.mean,结果是一样的。

setDT(dat)[, lapply(.SD, function(x) mean(x, na.rm = TRUE)), by = .(month), .SDcols = c("performance")]

使用简单均值后的结果如下,与weighted.mean的结果相同。

   month performance
1:     2   0.3576029
2:    10   0.3032712

期望的结果应该对每一年的表现给予同等重视,以便某一特定年份的出色表现不会错误地表明该产品每年在该月销售得很好。

有人能指出我的加权平均计算有什么问题吗?

【问题讨论】:

  • 什么叫加权平均?在 R 中,这意味着 ?weighted.mean,并且由于您没有给出任何权重,因此您得到的是正常平均值。
  • 在 package stats 的参考部分中,weighted.mean 提到了它——“如果 w 缺失,那么 x 的所有元素都被赋予相同的权重。”我想保持每年的权重相等。
  • 所以你得到一个正常的意思:那么问题是什么?
  • 如果每一年的权重相同,那么月份10的表现应该优于月份2。查看月份2 中的所有负值。我试图更好地解释它。如果我们找到performance 列的符号均值,那么月份10 是明显的赢家。 setDT(dat)[, lapply(.SD, function(x) mean(sign(x), na.rm = TRUE)), by = .(month), .SDcols = c("performance")]
  • 不,因为mean=sum/n 和您指出的第 8 行补偿了所有负值。您在寻找中位数吗?

标签: r data.table weighted-average


【解决方案1】:

你可以简单地remove outliers

remove_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
}
setDT(dat)[, lapply(.SD, function(x) mean(remove_outliers(x))), by = .(month), .SDcols = c("performance")]

month performance
1:     2   0.3576029
2:    10   0.4345511

或限制异常值,例如第一和第三四分位数:

limit_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  y <- x
  y[x < (qnt[1] )] <- qnt[1]
  y[x > (qnt[2] )] <- qnt[2] 
  y
}

setDT(dat)[, lapply(.SD, function(x) mean(limit_outliers(x), na.rm = TRUE)), by = .(month), .SDcols = c("performance")]

month performance
1:     2   0.3261458
2:    10   0.3432951

【讨论】:

  • 移除异常值并不能在完整数据集上给出最佳结果。是否可以限制可能影响最终结果的最大年份?例如在数据集 ``` 8: 2021 2 1.42862505``` 的第 8 行,最大性能为 1.42,我想将其视为不超过 1 (100%)。
【解决方案2】:

作为一个新的stackoverflow用户,我无法在帖子中添加commnets,所以我将在这里添加我的疑问。

一般来说,你提供的代码是一个简单的平均值,我不清楚你想要什么,因为通常当你想要一个加权平均值时,你会使用第二个变量作为权重。

在你的情况下,一个简单的平均值返回相同的输出:

library(dplyr)

dat %>% 
  group_by(month) %>% 
  summarise(performance = mean(performance))

【讨论】:

  • stats 包的参考部分中,提到了 weighted.mean - “如果 w 缺失,则 x 的所有元素都被赋予相同的权重。”我想保持每年的权重相等。
【解决方案3】:

如果您使用 weighted.mean 函数而不指定权重,它只会为您计算平均值。要正确计算,您可以在 weighted.mean 函数中将权重指定为第二个参数。

library(data.table)
dat <- structure(list(year = c(2014, 2015, 2016, 2017, 2018, 2019, 2020, 
                               2021, 2014, 2015, 2016, 2017, 2018, 2019, 2020), 
                      month = c(2, 
                                2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10), 
                      performance = c(0.826973794097158, 
                                      0.61975709469356, 0.924350659523548, -0.183133219063708, -0.529913189565746, 
                                      -0.148531188902535, -0.0773058814083695, 1.42862504650241, 0.465498268732376, 
                                      0.148719963224136, 0.205614191281359, 0.560651497949418, -0.484408605607923, 
                                      0.875353374774486, 0.351469397380814)), 
                 row.names = c(NA, -15L), class = c("data.table", "data.frame"))
head(dat)
setDT(dat)
dat[,.(weighted.mean(performance)), by = month]
dat[,.(mean(performance)), by = month]

R 执行

因此,要解决此问题,您可以执行以下操作: 在数据集中添加一列权重。我添加了 wt 变量作为我的权重。在这里,我只是简单地将序列 1 到 15 作为我的权重,您需要使用准确的值/权重来代替它。然后只需将此参数作为参数添加到您的 weighted.mean 函数中,我认为这应该可以解决您的问题。

dat$wt <- 1:nrow(dat)
weighted.mean(dat$performance,dat$wt) # will give you full column weighted mean
dat[,.(weighted.mean(performance,wt)), by = .(month)] # will give you weighted mean by month

R 结果:

【讨论】:

  • 这正是我面临的问题。 meanweighted.mean 都给出相同的结果。
  • 嗨,Saurabh,我在我的回答中添加了一些关于如何添加权重的更多信息。请检查,如果您仍有疑问,请告诉我,如果这就是您要找的。​​span>
  • 由于您使用了增量权重,这样做会增加近年来对过去几年的影响。这不是我要找的。我想限制一年业绩的最大影响,这样它就不会人为地提高任何一个月的业绩。
  • 我的重量只是为了你的例子..你可以根据你的方便使用它。如果您不想强调任何特定年份,使用加权平均值是没有意义的,因为这就是它的组成部分。我建议您使用其他一些度量,例如修剪均值或中位数,这样您就无需使用加权均值了。
  • 谢谢,Arup,Waldi 分享了一种修剪均值过程,同时限制了极值的影响。
猜你喜欢
  • 2019-09-22
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 2017-10-25
  • 2020-06-17
  • 2016-12-09
相关资源
最近更新 更多