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

如何基于df2的分布为df1填充Category1并拆分Vol值?

Python实现按比例拆分DataFrame的Vol字段(保持整数总和)

核心思路

  1. 从df2中提取Year/Month/Class/Region分组下Category1的分布比例
  2. 将该比例与df1合并,得到每个原始行对应的所有Category1条目
  3. 按比例计算初步整数拆分值,再调整误差确保拆分后总和与原Vol完全一致

代码实现

1. 导入依赖并构造示例数据

import pandas as pd
import numpy as np

# 示例df1:缺失Category1,需拆分Vol
df1 = pd.DataFrame({
    'Year': [2023, 2023],
    'Month': [1, 1],
    'Class': ['A', 'B'],
    'Region': ['North', 'South'],
    'Category2': ['X', 'Y'],
    'Category3': ['P', 'Q'],
    'Vol': [12, 17]
})

# 示例df2:包含Category1的分布数据
df2 = pd.DataFrame({
    'Year': [2023, 2023, 2023, 2023, 2023],
    'Month': [1, 1, 1, 1, 1],
    'Class': ['A', 'A', 'B', 'B', 'B'],
    'Region': ['North', 'North', 'South', 'South', 'South'],
    'Category1': ['C1', 'C2', 'C3', 'C4', 'C5'],
    'Other': [1, 2, 3, 4, 5]
})

2. 计算Category1的分布比例

# 按分组统计每个Category1的占比
cat1_proportions = df2.groupby(['Year', 'Month', 'Class', 'Region'])['Category1'] \
    .value_counts(normalize=True) \
    .reset_index(name='proportion')

3. 合并数据并初步拆分Vol

# 合并df1与比例表,关联每个原始行对应的所有Category1
merged = df1.merge(cat1_proportions, on=['Year', 'Month', 'Class', 'Region'], how='left')

# 计算初步整数拆分值(直接截断小数部分)
merged['split_vol'] = (merged['Vol'] * merged['proportion']).astype(int)

4. 调整误差保证总和一致

由于浮点运算取整后可能出现总和与原Vol的偏差,需将误差分配给比例最高的条目:

# 计算每个原始行的拆分总和与原Vol的差值
grouped_errors = merged.groupby(['Year', 'Month', 'Class', 'Region', 'Category2', 'Category3']) \
    .apply(lambda x: x['Vol'].iloc[0] - x['split_vol'].sum()) \
    .reset_index(name='error')

# 合并误差信息到表中
merged = merged.merge(grouped_errors, on=['Year', 'Month', 'Class', 'Region', 'Category2', 'Category3'])

# 按比例从高到低排序,将误差分配给前N个条目(N=error值)
merged['adjusted_split_vol'] = merged.apply(
    lambda row: row['split_vol'] + 1 if row.name in merged.sort_values(
        'proportion', ascending=False
    ).groupby([
        'Year', 'Month', 'Class', 'Region', 'Category2', 'Category3'
    ]).head(row['error']).index else row['split_vol'],
    axis=1
)

# 整理最终结果
result = merged.drop(['proportion', 'split_vol', 'error'], axis=1)
print(result)

关键说明

  • 使用value_counts(normalize=True)可以快速得到分组内Category1的占比分布
  • 误差调整逻辑优先给比例最高的条目加1,保证拆分结果最贴合原始比例
  • 如果df2中存在分组缺失的情况(即df1的分组在df2中没有对应Category1数据),可添加fillna逻辑处理,比如默认按均等比例拆分或标记异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:22:09