Pandas中for循环统计的持仓行业数据转独立DataFrame的Pythonic实现
券商持仓行业统计的Pythonic实现方案
核心思路
完全不需要手搓循环或者提前构造字典,直接用pandas原生的分组聚合能力实现:
- 自动遍历所有出现过的行业/子行业,无需硬编码任何具体分类值
- 直接输出结构化的DataFrame,替代零散的print输出
- 一次性实现需要的两层占比统计(子行业占全组合、子行业占所属母行业)
分步实现代码
1. 先计算全组合总市值
替代原代码中的total变量,一行搞定:
total = sectors_df['Current Value'].sum()
2. 生成母行业维度的统计DataFrame
和原代码第一个循环的计算逻辑完全等价,但输出是结构化表格:
# 按行业分组求总市值 sector_stats = sectors_df.groupby('Sector', as_index=False)['Current Value'].sum() # 重命名列方便后续识别 sector_stats = sector_stats.rename(columns={ 'Current Value': 'sector_total_value' }) # 计算行业占全组合的比例,保留2位小数 sector_stats['pct_of_total_portfolio'] = round( sector_stats['sector_total_value'] / total * 100, 2 )
生成的sector_stats中每一行,就对应原循环打印的x, value_in_sect, pct_in_sect三个值。
3. 生成子行业维度的统计DataFrame(包含需要的「子行业占母行业比例」)
这部分是原代码未实现的功能,同样用分组聚合实现:
# 按「母行业+子行业」双维度分组,求每个子行业的总市值 subsector_stats = sectors_df.groupby( ['Sector', 'Sub Sector'], as_index=False )['Current Value'].sum() # 重命名字段 subsector_stats = subsector_stats.rename(columns={ 'Current Value': 'subsector_total_value' }) # 关联对应母行业的总市值,用来计算子行业在母行业的占比 subsector_stats = subsector_stats.merge( sector_stats[['Sector', 'sector_total_value']], on='Sector', how='left' ) # 一次性计算两个子行业层面的占比 # 占全组合的比例 subsector_stats['pct_of_total_portfolio'] = round( subsector_stats['subsector_total_value'] / total * 100, 2 ) # 占所属母行业的比例(核心新增需求) subsector_stats['pct_of_parent_sector'] = round( subsector_stats['subsector_total_value'] / subsector_stats['sector_total_value'] * 100, 2 )
方案优势
- 零硬编码:不管后续持仓新增多少行业、子行业,代码完全不需要修改,自动覆盖所有分类值
- 效率更高:pandas的分组聚合是向量化操作,比原代码逐行过滤的循环速度快几十到上百倍,持仓量越大差距越明显
- 输出可复用:两个统计结果都是标准DataFrame,后续可以直接导出Excel、生成可视化图表、和其他持仓数据做关联分析,比零散的print结果好用太多
- 之前考虑的「构造字典再转DataFrame」的思路完全可行,但groupby+merge的写法是pandas的标准实践,不需要手动维护字典的键值对,出错概率更低
可选优化
如果持仓数据里存在空的行业/子行业值,可以在groupby前加一步数据清洗,自动过滤无效行:
sectors_df = sectors_df.dropna(subset=['Sector', 'Sub Sector'])
内容的提问来源于stack exchange,提问作者codian
相关产品推荐
相关产品推荐

