在R中两种方式计算月度聚合MAD结果不同的原因探究
问题分析与解决方法
为什么两种方法结果不同?
方法1是直接对月度内所有原始数据的abs(orig - new)值求均值,每个原始数据点的权重完全相等,这是全局算术平均,完全符合你要的月度MAD定义。
方法2的问题出在两步平均的逻辑漏洞:
- 第一步按天+小时分组,算出每个小时段的MAD(该小时内所有
abs(orig-new)的均值) - 第二步直接对这些小时MAD求算术平均
这里的核心矛盾是:每个小时段的数据量不一样,但你给了它们相同的权重。举个例子:
- 某天凌晨1点只有2条数据,算出的小时MAD值A
- 当天下午3点有200条数据,算出的小时MAD值B
在月度聚合时,A和B各占1份权重,但实际上B应该对应200份权重,A对应2份权重。直接求平均相当于把“小时”当成了等权重样本,而非回归到原始数据的权重,结果自然和方法1产生偏差。
修正方法2(保留分步逻辑,得到正确结果)
要让方法2和方法1结果一致,必须在小时分组时记录每个小时的样本量,然后月度聚合时做加权平均,权重就是每个小时的原始数据条数:
data_grouped_by_hour <- data %>% group_by( day = lubridate::floor_date(date, 'day'), hour = as.POSIXlt(time)$hour ) %>% summarise( mad_hour = mean(abs(orig - new)), n = n() # 记录每个小时的样本量 ) data_grouped_by_hour %>% group_by( month = lubridate::floor_date(day, 'month') # 注意:原代码用date会报错,分组后已无date列,改用day ) %>% summarise(mad = weighted.mean(mad_hour, w = n)) # 按样本量加权计算均值
简化写法(不用单独存中间表)
如果不想单独保存中间表,直接用管道串联即可:
data %>% group_by( day = lubridate::floor_date(date, 'day'), hour = as.POSIXlt(time)$hour ) %>% summarise( mad_hour = mean(abs(orig - new)), n = n(), .groups = "drop" # 解除分组,避免后续分组冲突 ) %>% group_by(month = lubridate::floor_date(day, 'month')) %>% summarise(mad = weighted.mean(mad_hour, w = n))
内容的提问来源于stack exchange,提问作者raven
相关产品推荐
相关产品推荐

