如何高效将Pandas单索引DataFrame扩展为多索引DataFrame?
高效实现区域-国家映射到区域-行业/国家-行业的扩展
基础数据与目标
首先定义基础的区域-国家映射矩阵,以及行业维度:
import pandas as pd concordance_region = pd.DataFrame( { "country 1": pd.Series([1, 0], index=["region a", "region b"]), "country 2": pd.Series([0, 1], index=["region a", "region b"]), "country 3": pd.Series([0, 1], index=["region a", "region b"]), } ) display(concordance_region) country_index = concordance_region.columns region_index = concordance_region.index sector_index = ['sector a','sector b'] country_sector = pd.MultiIndex.from_product([country_index, sector_index], names=["country", "sector"]) region_sector = pd.MultiIndex.from_product([region_index, sector_index], names=["region", "sector"])
我们需要生成如下扩展矩阵(无需硬编码数值):
concordance_region_expanded = pd.DataFrame([[1,0,0,0,0,0],[0,1,0,0,0,0],[0,0,1,0,1,0],[0,0,0,1,0,1]], index=region_sector, columns=country_sector) display(concordance_region_expanded)
现有低效方案
当前使用嵌套循环实现,不仅代码冗余,且处理大规模数据时效率极低:
concordance_region_extended = pd.DataFrame(index=region_sector, columns=country_sector) for region in region_index: for sector_1 in sector_index: for country in country_index: for sector_2 in sector_index: if sector_1 == sector_2 and concordance_region.loc[region, country] == 1: concordance_region_expanded.loc[(region, sector_1),(country, sector_2)] = 1 concordance_region_expanded = concordance_region_expanded.fillna(value=0).infer_objects(copy=False) concordance_region_expanded
更优解法:向量化运算(推荐)
利用NumPy的Kronecker积实现完全向量化操作,避免循环,效率提升显著:
原理
扩展逻辑等价于:区域-国家的映射矩阵 × 行业单位矩阵(同行业为1,不同为0)的Kronecker积,这样能直接生成符合要求的扩展矩阵。
import numpy as np # 创建行业单位矩阵:同行业匹配为1,不同为0 sector_identity = np.eye(len(sector_index)) # 计算Kronecker积,生成扩展后的数据 expanded_values = np.kron(concordance_region.values, sector_identity) # 构造最终的DataFrame concordance_region_expanded = pd.DataFrame( expanded_values, index=region_sector, columns=country_sector ) display(concordance_region_expanded)
备选解法:基于长格式数据的对齐
如果更倾向于Pandas原生操作,可通过长格式数据的合并与索引对齐实现:
# 将原始宽格式转换为长格式,保留匹配为1的记录 region_country_matches = concordance_region.stack().reset_index() region_country_matches.columns = ["region", "country", "match"] region_country_matches = region_country_matches[region_country_matches["match"] == 1] # 为每个匹配对关联所有行业(要求行业一致) region_country_matches = region_country_matches.assign(sector=sector_index).explode("sector") # 构造MultiIndex的行/列索引 region_country_matches["row"] = list(zip(region_country_matches["region"], region_country_matches["sector"])) region_country_matches["col"] = list(zip(region_country_matches["country"], region_country_matches["sector"])) # 初始化全0矩阵,填充匹配位置为1 concordance_region_expanded = pd.DataFrame(0, index=region_sector, columns=country_sector) concordance_region_expanded.loc[region_country_matches["row"], region_country_matches["col"]] = 1 display(concordance_region_expanded)
内容的提问来源于stack exchange,提问作者Y H
相关产品推荐
相关产品推荐

