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

求Pandas支持索引/列感知的单元格级apply函数及数据清洗优化方案

更高效的Pandas风格实现方案

你的核心痛点是双重循环的低效,我们可以通过向量化操作、广播机制和Pandas原生分组变换完全替代循环,同时保持逻辑清晰。以下是分步优化方案:

一、优化辅助计算步骤

1. 计算州级产品年度总量与季节性

替代嵌套apply,用groupby+reindex直接生成州级季节性占比:

# 州级产品年度总量(按Product+Year分组求和)
tot_annual = df.groupby(['Product', df.columns.str[:2]], axis=1).sum()
# 州级季节性:每个季度占当年州级总量的比例
tot_season = df / tot_annual.reindex(columns=df.columns, level=1).ffill(axis=1)

通过reindex+ffill把年度总量广播到每个季度列,直接做除法得到季节性,逻辑更简洁。

2. 验证县-产品年度数据有效性

用groupby+transform替代嵌套apply,批量验证数据有效性:

# 州级每个产品-年份的非零季度数
tot_nonzero = (df != 0).groupby(['Product', df.columns.str[:2]], axis=1).sum()
# 县级每个产品-年份的非零季度数(自动广播回原维度)
cty_nonzero = (df != 0).groupby(['Product', df.columns.str[:2]], axis=1).transform('sum')
# 标记有效年份:县级非零数等于州级非零数
cty_valid = cty_nonzero == tot_nonzero.reindex(columns=df.columns, level=1).ffill(axis=1)

3. 计算县-产品年度总量(广播到季度)

用transform自动生成与原表同维度的年度总量,无需手动重命名列:

cty_annual = df.groupby(['Product', df.columns.str[:2]], axis=1).transform('sum')

二、核心:向量化生成县级季节性矩阵

完全替代双重循环,用np.where结合广播机制一键生成cty_season:

# 计算县级实际季节性(仅有效年份可用)
actual_season = df / cty_annual
# 将州级季节性广播到县级维度(匹配每个县对应的Product)
state_season = tot_season.loc[df.index.get_level_values('Product')].values
# 按有效性选择使用实际或州级季节性
cty_season = pd.DataFrame(
    np.where(cty_valid, actual_season, state_season),
    index=df.index,
    columns=df.columns
)

通过df.index.get_level_values('Product')匹配每个县对应的产品,再用数组广播实现维度对齐,np.where完成条件选择。

三、最终生成调整后的数据

和原逻辑一致:

cty_adj = cty_season * cty_annual

完整优化代码

import pandas as pd
import numpy as np

data = [[73,  0,  0, 22,  0, 34,  5, 46],
        [51, 12, 77,  0, 19,  3,  0, 34],
        [73, 44,  1, 72,  0, 56, 21,  3],
        [ 3, 74,  2, 24,  4, 60,  8, 39],
        [70,  0, 36, 50,  3,  1, 59,  1],
        [14, 37, 26, 27, 87, 58, 95,  2],
        [ 4,  1, 17, 34, 25,  1,  1,  2],
        [ 0,  0,  0,  4, 18,  1,  8,  0],
        [42, 27, 41, 15, 67,  2, 25,  6]]

df = pd.DataFrame(data,
                  index=pd.MultiIndex.from_product([['County 1','County 2','County 3'],['A','B','C']],names=['County','Product']),
                  columns=pd.Series(['Y1Q1','Y1Q2','Y1Q3','Y1Q4','Y2Q1','Y2Q2','Y2Q3','Y2Q4'],name='Quarter'))

# 1. 计算州级产品年度总量与季节性
tot_annual = df.groupby(['Product', df.columns.str[:2]], axis=1).sum()
tot_season = df / tot_annual.reindex(columns=df.columns, level=1).ffill(axis=1)

# 2. 验证县-产品年度数据有效性
tot_nonzero = (df != 0).groupby(['Product', df.columns.str[:2]], axis=1).sum()
cty_nonzero = (df != 0).groupby(['Product', df.columns.str[:2]], axis=1).transform('sum')
cty_valid = cty_nonzero == tot_nonzero.reindex(columns=df.columns, level=1).ffill(axis=1)

# 3. 计算县-产品年度总量(广播到季度)
cty_annual = df.groupby(['Product', df.columns.str[:2]], axis=1).transform('sum')

# 4. 向量化生成县级季节性矩阵
actual_season = df / cty_annual
state_season = tot_season.loc[df.index.get_level_values('Product')].values
cty_season = pd.DataFrame(
    np.where(cty_valid, actual_season, state_season),
    index=df.index,
    columns=df.columns
)

# 5. 生成调整后的数据
cty_adj = cty_season * cty_annual

为什么这更Pandas化?

  • 无循环:完全用向量化操作替代逐元素循环,大数据量下性能提升显著
  • 原生API:依赖groupby、transform等核心功能,逻辑易读易维护
  • 广播机制:自动对齐维度,避免手动处理索引/列名
  • 可复用性:只需调整列名切片规则,就能扩展到月度数据或其他层级的行政区划

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:34:59