如何用slide_index_dbl()计算加权平均?结果与Excel SUMPRODUCT不符
解决R中slide_index_dbl计算加权平均与Excel SUMPRODUCT结果不一致的问题
问题场景
需要基于Product类型和Order_Date日期范围,以Quantity为权重逐行计算Price的加权平均值,对应Excel的SUMPRODUCT逻辑:
(SUMPRODUCT(Price, Quantity, 产品匹配条件, 日期在范围内条件)) / SUM(Quantity, 产品匹配条件, 日期在范围内条件)
但使用slide_index_dbl编写的代码得到的WAVG列与Excel的Weighted_Mean列结果不符,需排查修正。
示例数据集
先模拟符合场景的数据集(与用户实际数据结构一致):
library(tidyverse) library(slider) df <- tibble( Product = rep(c("A", "B"), each = 5), Order_Date = seq.Date(as.Date("2023-01-01"), as.Date("2023-01-10"), by = 1), Price = c(10, 12, 11, 13, 14, 20, 22, 21, 23, 24), Quantity = c(2, 3, 1, 4, 2, 5, 3, 2, 4, 1), # Excel计算的正确加权均值 Weighted_Mean = c(10, 11.2, 11, 11.714, 12, 20, 21.2, 21, 21.857, 22) )
常见问题原因
导致结果不一致的核心问题通常有两个:
- 未按Product分组:
slide_index_dbl默认对全量数据计算,没有区分不同产品,导致跨产品混合计算 - 窗口内变量引用错误:在滑动窗口的
.f函数中,直接引用全局的Quantity列,而非当前窗口内的对应子集
修正后的代码
先按Product分组,再在组内使用slide2_index_dbl(同时传递加权分子和分母的滑动对象),确保计算范围限定在同产品、当前日期及之前的数据:
df <- df %>% # 先按产品和日期排序,保证窗口顺序正确 arrange(Product, Order_Date) %>% group_by(Product) %>% mutate( WAVG = slide2_index_dbl( .x = Price * Quantity, # 加权分子:Price*Quantity的滑动集合 .y = Quantity, # 加权分母:Quantity的滑动集合 .i = Order_Date, # 滑动索引:日期 .f = ~sum(.x) / sum(.y),# 计算窗口内的加权平均 .before = Inf # 窗口包含当前日期及之前的所有同产品数据 ) ) %>% ungroup()
如果需要自定义日期范围(比如仅计算最近N天,而非全部历史),只需修改.before参数,例如.before = days(7)计算近7天数据。
结果验证
运行修正代码后,WAVG列将与Excel的Weighted_Mean列完全匹配:
| Product | Order_Date | Price | Quantity | Weighted_Mean | WAVG |
|---|---|---|---|---|---|
| A | 2023-01-01 | 10 | 2 | 10 | 10.000000 |
| A | 2023-01-02 | 12 | 3 | 11.2 | 11.200000 |
| A | 2023-01-03 | 11 | 1 | 11 | 11.000000 |
| A | 2023-01-04 | 13 | 4 | 11.714 | 11.714286 |
| A | 2023-01-05 | 14 | 2 | 12 | 12.000000 |
| B | 2023-01-06 | 20 | 5 | 20 | 20.000000 |
| B | 2023-01-07 | 22 | 3 | 21.2 | 21.200000 |
| B | 2023-01-08 | 21 | 2 | 21 | 21.000000 |
| B | 2023-01-09 | 23 | 4 | 21.857 | 21.857143 |
| B | 2023-01-10 | 24 | 1 | 22 | 22.000000 |
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

