You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中计算各因子的工作日周均值(含非整周处理)

问题描述

现有一个包含三列的DataFrame,包含A、B、C三个因子,每个因子在指定时间范围内的每个工作日都有对应数值。模拟代码如下:

import pandas as pd
import numpy as np

index_d = pd.bdate_range(start='10/5/2022', end='10/27/2022')
index = np.repeat(index_d,3)
values = np.random.randn(3*len(index_d), 1)
columns_v = len(index_d)*["A","B","C"]
df = pd.DataFrame()
df["x"] = np.asarray(index)
df["y"] = values
df["factor"] = np.asarray([columns_v]).T

需求:绘制三个因子的工作日周均值随时间变化的折线图,工作日周定义为周一至周五。由于起始和结束日期不在整周首尾,第一周均值仅包含10月5日、6日、7日的数据,最后一周同理。周均值对应的时间为该周最后一个工作日(通常为周五,最后一周为周四),最终输出格式需匹配如下结构:

import datetime as dt
dt1 = dt.datetime.strptime("20221007", "%Y%m%d").date()
dt2 = dt.datetime.strptime("20221014", "%Y%m%d").date()
dt3 = dt.datetime.strptime("20221021", "%Y%m%d").date()
dt4 = dt.datetime.strptime("20221027", "%Y%m%d").date()

d = 3*[dt1, dt2, dt3, dt4]
values = np.random.randn(len(d), 1)
factors = 4*["A","B","C"]
df_output = pd.DataFrame()
df_output["time"] = d
df_output["values"] = values
df_output["factors"] = factors
解决方案

步骤1:数据预处理

先确保日期列是datetime类型,避免分组出错:

df['x'] = pd.to_datetime(df['x'])

步骤2:分组计算周均值

使用groupby结合pd.Grouper按周五结束的周分组,同时计算每个因子的周均值,并保留该周的最后一个工作日作为时间标签:

# 分组计算:按因子+周分组,取y的均值,以及该组的最后日期
df_grouped = df.groupby(
    ['factor', pd.Grouper(key='x', freq='W-FRI')], 
    dropna=False
).agg(
    values=('y', 'mean'),  # 计算均值,默认跳过NaN
    time=('x', 'max')      # 取该周最后一个实际工作日
).reset_index(drop=True)

关键细节说明:

  • pd.Grouper(key='x', freq='W-FRI'):按周五作为周的结束点分组,自动适配非整周的起始/结束数据(比如第一周仅包含10.5-10.7,最后一周包含10.24-10.27)。
  • dropna=False:保留包含NaN的分组(若需剔除可改为dropna=True);mean方法默认跳过NaN值,若需包含NaN计算可改为mean(skipna=False)。
  • time=('x', 'max'):确保每个周均值对应的时间是该组实际存在的最后一个工作日,完美匹配需求。

步骤3:绘制折线图

使用Seaborn的lineplot,通过hue参数区分不同因子:

import seaborn as sns
import matplotlib.pyplot as plt

sns.lineplot(data=df_grouped, x='time', y='values', hue='factor')
plt.xticks(rotation=45)  # 旋转日期标签避免重叠
plt.tight_layout()       # 自动调整布局
plt.show()
性能与NaN处理补充
  • 大数据量适配:groupby结合pd.Grouper是Pandas原生高效分组方式,无需自定义复杂逻辑,适合大规模数据集。
  • NaN处理:若需过滤掉存在NaN的行,可在分组前执行df = df.dropna(subset=['y']);若需排除整个存在NaN的周,可在分组后执行df_grouped = df_grouped.dropna(subset=['values'])。

内容的提问来源于stack exchange,提问作者swissy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:25:18