如何基于df2的分布为df1填充Category1并拆分Vol值?
Python实现按比例拆分DataFrame的Vol字段(保持整数总和)
核心思路
- 从df2中提取
Year/Month/Class/Region分组下Category1的分布比例 - 将该比例与df1合并,得到每个原始行对应的所有
Category1条目 - 按比例计算初步整数拆分值,再调整误差确保拆分后总和与原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
相关产品推荐
相关产品推荐

