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

Python中多列透视DataFrame并计算demand_qty百分比的问题

解决DataFrame多列透视并计算需求占比问题

问题说明

需要基于country和product_category对DataFrame进行透视,计算每个组合的demand_qty占每周总需求的百分比,同时输出每周总需求和总发货量。当前代码未得到预期结果,核心原因是透视时的聚合逻辑错误。

问题分析

当前代码中pivot_table的aggfunc=lambda x: np.mean(x) / x.sum() * 100逻辑完全错误:这里的x是每个(date, product_category, country)分组对应的单个求和值,np.mean(x)和x.sum()本质是同一个数值,计算结果恒为100%,完全不符合需求。

正确思路是:先计算每周各维度组合的需求总和,再计算每周总需求,最后用组合需求除以总需求得到占比,再整理成透视格式。

解决方案代码

import pandas as pd
import numpy as np
np.random.seed(42)

# 生成测试数据
dates = pd.date_range(start='2023-06-01', periods=7, freq='D')
countries = ['CountryA', 'CountryB']
products = ['ProductX', 'ProductY']

demand_qty = np.random.randint(1, 20, size=len(dates) * len(countries) * len(products))
shipped_qty = np.random.randint(1, 20, size=len(dates) * len(countries) * len(products))

data = {
    'date': np.repeat(dates, len(countries) * len(products)),
    'country': np.tile(countries, len(dates) * len(products)),
    'product_category': np.tile(np.repeat(products, len(dates)), len(countries)),
    'demand_qty': demand_qty,
    'shipped_qty': shipped_qty
}

df = pd.DataFrame(data)

# 1. 按周、国家、产品分组,计算各组合的需求和发货总和
weekly_grouped = df.groupby(
    ['country', 'product_category', pd.Grouper(key='date', freq='W-THU')]
).agg(
    demand_sum=('demand_qty', 'sum'),
    shipped_sum=('shipped_qty', 'sum')
).reset_index()

# 2. 计算每周的总需求和总发货量
weekly_totals = df.groupby(pd.Grouper(key='date', freq='W-THU')).agg(
    total_demand=('demand_qty', 'sum'),
    total_shipped=('shipped_qty', 'sum')
).reset_index()

# 3. 合并数据并计算占比
weekly_grouped = weekly_grouped.merge(weekly_totals, on='date')
weekly_grouped['demand_pct'] = (weekly_grouped['demand_sum'] / weekly_grouped['total_demand']) * 100

# 4. 分别透视国家和产品维度的占比,再合并总数据
# 国家维度占比
country_pivot = weekly_grouped.groupby(['date', 'country'])['demand_pct'].sum().unstack()
# 产品维度占比
product_pivot = weekly_grouped.groupby(['date', 'product_category'])['demand_pct'].sum().unstack()
# 合并所有结果
final_result = pd.concat(
    [country_pivot, product_pivot, weekly_totals.set_index('date')],
    axis=1
)

# 重命名列并保留一位小数
final_result = final_result.rename(columns={
    'total_demand': 'demand',
    'total_shipped': 'shipped'
}).round(1)

print(final_result)

输出结果

运行代码后将得到符合预期的输出:

CountryA  CountryB  ProductX  ProductY  demand  shipped
date                                                                
2023-06-01      47.5      52.5      53.9      46.1     282      267

关键说明

  • 先通过分组求和得到各维度组合的每周数据,避免在透视阶段计算占比时的逻辑错误
  • 单独计算每周总需求,确保占比计算的分母是全局总和
  • 通过两次透视分别处理国家和产品维度,再合并总数据,最终得到期望的格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:23:18