
本文介绍如何基于 3 个及以上列对 dataframe 进行分组,并递归构建嵌套字典,将指定值列(如 area_sub_code_1/2)按 region→country→area_code 多级键组织为列表或单值映射。
本文介绍如何基于 3 个及以上列对 dataframe 进行分组,并递归构建嵌套字典,将指定值列(如 area_sub_code_1/2)按 region→country→area_code 多级键组织为列表或单值映射。
在 Pandas 中,直接使用 groupby() 对 4 列或更多列进行迭代时,常见错误如 too many values to unpack (expected 2),其根源在于 df.groupby([...])[col] 返回的是一个 SeriesGroupBy 对象,而解包语法 for (k1, k2), v in ... 仅适配二元元组索引——当分组列数超过 2 时,索引变为 MultiIndex,需改用更通用的递归处理方式。
✅ 推荐方案:熔解 + 分层索引 + 递归字典构建
核心思路分三步:
-
熔解(melt):将多个目标值列(如
AREA_SUB_CODE_1,AREA_SUB_CODE_2)统一转为长格式,新增sub_code列标识来源; -
构建多级索引:以
['sub_code', 'Region', 'Country', 'AREA_CODE']为索引,生成Series; - 递归展开:编写泛化函数,逐层遍历 MultiIndex,最终在叶节点提取唯一值并转为列表。
? 示例代码实现
import pandas as pd
# 构造示例数据
df = pd.DataFrame({
'Region': ['AMER', 'AMER', 'AMER', 'AMER'],
'Country': ['US', 'CANADA', 'US', 'US'],
'AREA_CODE': ['A1', 'A1', 'B1', 'A1'],
'AREA_SUB_CODE_1': ['A1_US_1x', 'A1_CA_1', 'B1_US_1', 'A1_US_1y'],
'AREA_SUB_CODE_2': ['A1_US_2', 'A1_CA_2', 'B1_US_2', 'A1_US_2']
})
# Step 1: 熔解,将 SUB_CODE 列转为长格式
inner_cols = ['Region', 'Country', 'AREA_CODE']
melted = df.melt(
id_vars=inner_cols,
value_vars=['AREA_SUB_CODE_1', 'AREA_SUB_CODE_2'],
var_name='sub_code',
value_name='value'
)
# Step 2: 设置多级索引并压缩为 Series
indexed_series = melted.set_index(['sub_code', *inner_cols])['value'].squeeze()
# Step 3: 递归构建嵌套字典(支持任意层级,自动处理重复值)
def build_nested_dict(s):
if s.index.nlevels > 1:
return {k: build_nested_dict(s[k]) for k in s.index.levels[0]}
else:
# 叶节点:对每个键提取所有唯一值 → 转为 list
return {k: s.loc[[k]].unique().tolist() for k in s.index.unique()}
result = build_nested_dict(indexed_series)? 输出结构说明
运行后 result 即为符合预期的嵌套字典:
{
'AREA_SUB_CODE_1': {
'AMER': {
'CANADA': {'A1': ['A1_CA_1']},
'US': {'A1': ['A1_US_1x', 'A1_US_1y'], 'B1': ['B1_US_1']}
}
},
'AREA_SUB_CODE_2': {
'AMER': {
'CANADA': {'A1': ['A1_CA_2']},
'US': {'A1': ['A1_US_2'], 'B1': ['B1_US_2']}
}
}
}✅ 优势:完全动态,无需硬编码列数;自动去重;天然支持 3、4、5+ 列分组;兼容含重复值与唯一值混合场景。
⚠️ 注意事项与优化建议
-
性能提示:若数据量极大(>100 万行),递归可能带来栈开销,可改用迭代式 DFS 或
defaultdict手动构建; -
空值处理:
s.loc[[k]]在缺失键时会报错,生产环境建议包裹try/except或预检k in s.index; -
单值优化:若确认末级值严格唯一(如主键映射),可将叶节点逻辑简化为
s.to_dict(),提升效率; -
扩展性:只需修改
value_vars和inner_cols,即可适配任意数量的分组列与目标值列。
该方法摆脱了传统 groupby 解包限制,以数据整形(melt)+ 索引抽象(MultiIndex)+ 函数式递归为核心,是构建高维聚合字典的稳健范式。

















