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

如何高效实现按星期分组后对多列应用trim_mean函数?

高效实现按星期分组的截尾均值计算

需求说明

现有包含700天每日5项测量数据的数据集,需要按星期几分组后,对每个测量项应用scipy.stats.trim_mean函数,其中proportiontocut参数设为1/该组数据的标准差。原实现方式需逐个列手动处理,效率极低,需优化为简洁高效的批量处理方案。

原始数据生成代码

import pandas as pd
import numpy as np
from scipy.stats import trim_mean

np.random.seed(42)

data = np.random.randint(0, 100, size=(5, 700))
col_names = pd.date_range('11-16-2023', periods=700)
df = pd.DataFrame(data, columns=col_names)

优化后的实现方案

核心思路

  1. 定义通用计算函数,封装截尾均值的计算逻辑,同时处理边界问题(避免标准差为0导致的除以0错误,且保证proportiontocut符合trim_mean的参数范围要求:0 ≤ proportiontocut ≤ 0.5)
  2. 使用groupby.agg()对所有测量列批量应用函数,无需手动遍历每一列
  3. 最后调整结果格式,匹配需求的输出样式

完整优化代码

# 转置数据并添加星期几列
df_T = df.T
df_T['Day of Week'] = pd.to_datetime(df_T.index).isocalendar().day

# 定义通用的截尾均值计算函数
def calc_trim_mean(x):
    std_val = np.std(x)
    # 处理标准差为0的情况,同时限制proportiontocut在0到0.5之间
    proportion = 1 / std_val if std_val != 0 else 0
    proportion = np.clip(proportion, 0, 0.5)
    return trim_mean(x, proportiontocut=proportion)

# 批量计算所有列的分组截尾均值
grouped_results = df_T.groupby('Day of Week').agg(calc_trim_mean)

# 调整结果格式:转置后修改列名为星期全称
results_df = grouped_results.T
results_df.columns = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

# 查看结果
print(results_df)

输出结果

Mon        Tue        Wed        Thu        Fri        Sat        Sun
0  50.936170  51.712766  44.659574  49.117021  48.702128  47.414894  51.223404
1  49.244681  49.000000  49.138298  49.191489  45.872340  49.010638  47.074468
2  49.436170  46.404255  49.021277  46.553191  55.031915  51.265957  50.638298
3  43.744681  47.787234  48.574468  45.882979  47.255319  47.914894  49.606383
4  49.265957  46.255319  50.276596  50.872340  46.723404  45.255319  49.904255

优势说明

  • 批量处理:无论测量项数量多少,无需修改代码,自动处理所有列
  • 鲁棒性强:添加了标准差为0的异常处理,避免运行时错误
  • 代码简洁:将重复逻辑封装为函数,结构清晰易维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:46:22