基于Variant维度的多列自定义窗口大小移动平均实现问题
问题排查与解决:按Variant计算移动平均的函数错误
问题背景
现有一个包含Date、Measurement 1至Measurement 10、Variant字段的大型多维DataFrame,已通过window_s_prüfpunkte函数计算每个Variant近两个月的出现频次平均值,代码如下:
def window_s_prüfpunkte(df, config_col, date_col, data_cols): results = {} for config in df[config_col].unique(): config_df = df[df[config_col] == config] date_series = pd.to_datetime(config_df[date_col]) monthly_count = config_df.groupby([date_series.dt.year, date_series.dt.month]).count().rename_axis(['year', 'month'])[data_cols].reset_index() quantity_average = round(monthly_count[data_cols].mean().mean()) results[config] = {'monthly_count': monthly_count, 'quantity_average': quantity_average} return results unique_configs = FSC3_Z_df_12M['Configuration Summary'].unique() window_results = {} for config in unique_configs: config_df = FSC3_Z_df_12M[FSC3_Z_df_12M['Configuration Summary'] == config] window_results[config] = window_s_prüfpunkte(config_df, 'Configuration Summary', 'Datum LP', COLS_Delta_Z)
尝试编写moving_average_by_config函数,以每个Variant的平均值为窗口大小计算各Measurement列的移动平均,但函数无法正常运行:
def moving_average_by_config(df, config_col, date_col, data_cols, window_results): results = [] for config in df[config_col].unique(): config_df = df[df[config_col] == config] config_window_size = window_results[config] for data_col in data_cols: config_df[f'{data_col}_MA'] = config_df[data_col].rolling(window=config_window_size).mean() results.append(config_df) return pd.concat(results)
错误分析
- 窗口大小取值错误:
window_results是双层嵌套字典,每个config对应的是window_s_prüfpunkte返回的完整结果字典(包含monthly_count和quantity_average),但rolling需要整数类型的窗口大小,直接传整个字典会触发类型错误。 - 冗余的循环调用:外层循环遍历每个config并单独传入
window_s_prüfpunkte,但该函数内部已经会遍历所有unique config,完全可以直接传入整个DataFrame,避免重复计算。 - 视图修改警告:直接修改切片得到的
config_df(DataFrame视图)会触发SettingWithCopyWarning,可能导致修改不生效或意外行为。
修复后的代码
第一步:修复窗口结果的生成逻辑
去掉冗余的外层循环,直接调用一次函数即可:
# 直接传入整个DataFrame,无需单独遍历config window_results = window_s_prüfpunkte(FSC3_Z_df_12M, 'Configuration Summary', 'Datum LP', COLS_Delta_Z)
第二步:修复移动平均函数
修正窗口大小的取值路径,同时创建DataFrame副本避免视图修改问题:
def moving_average_by_config(df, config_col, data_cols, window_results): results = [] for config in df[config_col].unique(): # 创建副本,避免视图修改警告 config_df = df[df[config_col] == config].copy() # 取出对应的窗口大小数值 config_window_size = window_results[config]['quantity_average'] # 跳过窗口大小为0的情况(避免rolling报错) if config_window_size <= 0: for data_col in data_cols: config_df[f'{data_col}_MA'] = None else: for data_col in data_cols: config_df[f'{data_col}_MA'] = config_df[data_col].rolling(window=config_window_size).mean() results.append(config_df) return pd.concat(results)
额外说明
- 新增了窗口大小为0的判断逻辑,避免因计算出的平均值为0导致
rolling函数报错。 - 原函数中的
date_col参数在移动平均计算中未被使用,因此可以移除,简化函数参数。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

