三变量(date、campaign、country)索引的dataframe Rolling average计算问题
三索引DataFrame移动平均计算实现方案
核心逻辑很简单:滚动计算仅需要按非时间的索引维度分组,每个分组内是独立的时间序列,按时间排序后执行滚动计算即可,三个索引的场景只需要把两个非时间维度都加入分组字段即可,也适配任意多维度索引场景。
R 实现(tidyverse 生态)
推荐使用slider包的滑动计算函数,原生适配dplyr语法:
library(dplyr) library(slider) df_rolled <- df %>% # 按campaign、country两个非时间维度分组 group_by(campaign, country) %>% # 保证分组内数据按日期升序排列,是滚动计算正确性的前提 arrange(date, .by_group = TRUE) %>% # 以7天移动平均为例,调整.window参数修改窗口大小 mutate( cost_ma7 = slide_dbl(cost, mean, .window = 7, .complete = FALSE), clicks_ma7 = slide_dbl(clicks, mean, .window = 7, .complete = FALSE) ) %>% ungroup()
参数说明:
.complete = FALSE表示窗口大小不足时也返回已有数据的均值,若设为TRUE,窗口大小不足的行将返回NA- 如果需要按自然日窗口(而非数据行数)计算,可以将
.before参数设置为lubridate::days(6),同时保证date列为日期格式
Python 实现(pandas 生态)
基于pandas多级索引和分组滚动计算实现:
import pandas as pd # 将三个索引字段设为多级索引并排序 df = df.set_index(['campaign', 'country', 'date']).sort_index() # 按campaign、country分组,计算7天移动平均 df[['cost_ma7', 'clicks_ma7']] = df.groupby(level=['campaign', 'country'])[['cost', 'clicks']] \ .rolling(window=7, min_periods=1).mean() # 重置索引恢复为普通列格式,原三个索引字段完整保留 df = df.reset_index()
参数说明:
min_periods=1表示窗口大小不足时也返回有效值,修改为等于窗口大小即可要求窗口满数据才返回结果- 如果要按自然日而非数据行数计算窗口,可以将
window参数替换为window='7D'
内容的提问来源于stack exchange,提问作者João Paulo
相关产品推荐
相关产品推荐

