如何高效将Pandas分组后的多层索引结果转为嵌套字典
问题:将多层索引Series转换为嵌套字典的高效实现
场景与需求
执行以下分组统计代码后:
df.groupby(by=["Unit","Product","Scheme","Type"]).size()
得到多层索引的Series结果:
Unit Product Scheme Type JBBNB BP KRZPS MRTZN 13 TOPUP 5 ZBPRE 3 HB KRJZS CONST 6 FZNEW 5 .. htrcy HB TNJZS PZTCN 2 TNBTS TOEJZ 2 TU TNTPS BDDFIN 2 TOPUP 1 hwrng BP TGZPS ZBPRE 1 Length: 1632, dtype: int64
需要将其转换为如下结构的嵌套字典:
{ "JBBNB": {"BP": {"KRZPS":{"MRTZN":13,"TOPUP":5,"ZBPRE":3}}, "HB":{"KRJZS":{"CONST":6,"FZNEW":5}} }, "htrcy": {"HB": {"TNJZS":{"PZTCN":2}, "TNBTS":{"TOEJZ":2}}, "TU":{"TNTPS":{"BDDFIN":2,"TOPUP":1}}, } }
补充数据示例:
data = {"Unit": {"31-08": "JBJEB", "22-11": "JBGRB", "06-04": "JBGRB", "29-11": "JBZWI", "15-02": "JBGRB", "28-02": "JBJEB", "23-03": "JBGRB", "13-06": "JBJEB", "30-06": "JBMDR", "20-07": "JBJEB", "23-07": "JBJEB", "25-07": "JBJEB", "23-08": "JBJEB", "30-09": "JBZWR", "22-10": "JBJEB", "27-12": "JBJMD", "31-12": "JBJEB", "25-03": "JBJEB", "29-03": "JBJEB", "29-04": "JBJEB", "29-07": "JBJEB", "18-06": "JBJMD", "30-07": "JBMDR", "10-08": "JBJMR", "24-03": "JBJMD", "19-07": "JBJMD", "26-12": "JBJMD", "31-03": "JBJMR", "08-09": "JBJMR", "07-10": "JBJMR", "10-05": "JBJMR", "28-07": "JBJMR", "27-09": "JBJMR", "27-11": "JBJMR", "30-11": "JBJMR", "22-12": "JBJMR", "24-07": "JBZJB", "23-09": "JBZWI", "29-09": "JBZWI", "07-02": "JBZWI", "14-10": "JBZWR", "23-12": "JBZWR", "29-08": "JBZWR", "18-11": "JBZWR", "21-12": "JBZWR", "03-01": "JBZWR", "28-08": "JBZWR", "20-09": "JBMDR", "02-12": "JBMDR"}, "Product": {"31-08": "TU", "22-11": "TU", "06-04": "TU", "29-11": "TU", "15-02": "TU", "28-02": "TU", "23-03": "TU", "13-06": "TU", "30-06": "TU", "20-07": "TU", "23-07": "TU", "25-07": "TU", "23-08": "TU", "30-09": "TU", "22-10": "TU", "27-12": "TU", "31-12": "TU", "25-03": "TU", "29-03": "TU", "29-04": "TU", "29-07": "TU", "18-06": "TU", "30-07": "TU", "10-08": "TU", "24-03": "TU", "19-07": "TU", "26-12": "TU", "31-03": "TU", "08-09": "BP", "07-10": "TU", "10-05": "TU", "28-07": "TU", "27-09": "TU", "27-11": "TU", "30-11": "TU", "22-12": "TU", "24-07": "TU", "23-09": "TU", "29-09": "TU", "07-02": "TU", "14-10": "BP", "23-12": "BP", "29-08": "TU", "18-11": "TU", "21-12": "TU", "03-01": "TU", "28-08": "TU", "20-09": "TU", "02-12": "TU"}, "Scheme": {"31-08": "GJTPS", "22-11": "UPTPS", "06-04": "UPTPS", "29-11": "UKTPS", "15-02": "UPTPS", "28-02": "GJTPS", "23-03": "UPTPS", "13-06": "GJTPS", "30-06": "MJTPS", "20-07": "GJTPS", "23-07": "GJTPS", "25-07": "GJTPS", "23-08": "GJTPS", "30-09": "RJTPS", "22-10": "GJTPS", "27-12": "GJTPS", "31-12": "GJTPS", "25-03": "GJTPS", "29-03": "GJTPS", "29-04": "GJTPS", "29-07": "GJTPS", "18-06": "GJTPS", "30-07": "MJTPS", "10-08": "RJTPS", "24-03": "GJTPS", "19-07": "GJTPS", "26-12": "GJTPS", "31-03": "RJTPS", "08-09": "RJZPS", "07-10": "RJTPS", "10-05": "RJTPS", "28-07": "RJTPS", "27-09": "RJTPS", "27-11": "RJTPS", "30-11": "RJTPS", "22-12": "RJTPS", "24-07": "UPTPS", "23-09": "UKTPS", "29-09": "UKTPS", "07-02": "UKTPS", "14-10": "RJZPS", "23-12": "RJZPS", "29-08": "RJTPS", "18-11": "RJTPS", "21-12": "RJTPS", "03-01": "RJTPS", "28-08": "RJTPS", "20-09": "MJTPS", "02-12": "MJTPS"}, "Type": {"31-08": "BDDFIN", "22-11": "BDDFIN", "06-04": "BDDFIN", "29-11": "BDDFIN", "15-02": "BDDFIN", "28-02": "BDDFIN", "23-03": "BDDFIN", "13-06": "BDDFIN", "30-06": "BDDFIN", "20-07": "BDDFIN", "23-07": "BDDFIN", "25-07": "BDDFIN", "23-08": "BDDFIN", "30-09": "BDDFIN", "22-10": "BDDFIN", "27-12": "BDDFIN", "31-12": "BDDFIN", "25-03": "BDDFIN", "29-03": "BDDFIN", "29-04": "BDDFIN", "29-07": "BDDFIN", "18-06": "BDDFIN", "30-07": "BDDFIN", "10-08": "BDDFIN", "24-03": "BDDFIN", "19-07": "BDDFIN", "26-12": "BDDFIN", "31-03": "BDDFIN", "08-09": "BDDFIN", "07-10": "BDDFIN", "10-05": "BDDFIN", "28-07": "BDDFIN", "27-09": "BDDFIN", "27-11": "BDDFIN", "30-11": "BDDFIN", "22-12": "BDDFIN", "24-07": "BDDFIN", "23-09": "BDDFIN", "29-09": "BDDFIN", "07-02": "BDDFIN", "14-10": "BDDFIN", "23-12": "BDDFIN", "29-08": "BDDFIN", "18-11": "BDDFIN", "21-12": "BDDFIN", "03-01": "BDDFIN", "28-08": "BDDFIN", "20-09": "BDDFIN", "02-12": "BDDFIN"}} df = pd.DataFrame(data)
高效实现方法
方法1:直接遍历多层索引(性能最优)
直接遍历Series的多层索引与对应值,通过dict.setdefault逐层构建嵌套字典,无额外数据转换开销,适合大数据量场景:
# 先获取分组统计结果 s = df.groupby(by=["Unit","Product","Scheme","Type"]).size() # 初始化结果字典 result = {} # 遍历每一组的索引和计数 for (unit, product, scheme, typ), count in s.items(): # 逐层创建嵌套字典 result.setdefault(unit, {}).setdefault(product, {}).setdefault(scheme, {})[typ] = count
方法2:递归构造字典(代码更规整)
如果分组层级不确定或需要灵活适配,可使用递归方法,结合DataFrame分组逻辑构建嵌套结构:
s = df.groupby(by=["Unit","Product","Scheme","Type"]).size().reset_index(name='count') def build_nested(df, levels): if len(levels) == 1: return df.set_index(levels[0])['count'].to_dict() return { group_key: build_nested(group_df.drop(levels[0], axis=1), levels[1:]) for group_key, group_df in df.groupby(levels[0]) } result = build_nested(s, ['Unit', 'Product', 'Scheme', 'Type'])
效率说明
- 方法1在数据量较大时(如示例中的1632条数据)性能更优,直接操作索引和值,避免了DataFrame分组的额外开销。
- 方法2代码结构更清晰,适合层级动态变化的场景,性能略逊于方法1,但差距在可接受范围内。
内容的提问来源于stack exchange,提问作者Mogli141
相关产品推荐
相关产品推荐

