You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas多索引创建与DataFrame动态转指定字典的内置方法问询

解决你的两个Pandas技术需求

1. 为DataFrame创建多索引

Pandas内置的set_index()方法可以轻松实现多索引(层级索引),只需要传入你想作为索引的列名列表即可。比如你想把country和name设为多索引:

import pandas as pd

# 构造示例DataFrame
data = {
    'name': ['user1', 'user2', 'user3', 'user4', 'user5', 'user6'],
    'age': [10, 11, 12, 13, 14, 15],
    'country': ['in', 'in', 'eu', 'eu', 'us', 'us'],
    'state': ['tn', 'tx', 'gh', 'io', 'pi', 'ew'],
    'pincode': [1, 2, 3, 4, 5, 6]
}
df = pd.DataFrame(data)

# 创建多索引
multi_index_df = df.set_index(['country', 'name'])

这样得到的multi_index_df就拥有了两层索引,后续你可以通过multi_index_df.loc['in', 'user1']快速定位目标行数据。

2. 动态转换为指定格式的字典

先说说你现有代码的问题:

  • 初始化op2[row['country']]为列表,但后续直接赋值成单个字典,导致每次循环都会覆盖之前的用户数据,最终每个国家下只剩最后一个用户的信息;
  • 硬编码了age、state、pincode列,新增列(比如telephone)时需要手动修改代码,无法动态适配。

Pandas有更优雅的内置方法可以解决这个问题,而且完全支持动态列,不需要硬编码任何列名:

# 转换为目标格式字典的代码
result = df.set_index('name').groupby('country').apply(lambda x: x.drop(columns='country').to_dict('index')).to_dict()

代码解释:

  1. df.set_index('name'):把name列设为DataFrame的索引,方便后续转成以name为键的字典;
  2. .groupby('country'):按country分组,把同一国家的用户归为一组;
  3. .apply(lambda x: x.drop(columns='country').to_dict('index')):对每个分组执行操作:
    • 先去掉country列(因为它已经作为外层字典的键了);
    • 用to_dict('index')把分组内的DataFrame转成以name(索引)为键,行内所有字段为值的字典;
  4. .to_dict():最后把分组结果整体转成外层以country为键的字典。

这样即使你给DataFrame新增telephone列,比如:

df['telephone'] = ['123', '456', '789', '012', '345', '678']

再运行上面的转换代码,结果里会自动包含telephone字段,完全不需要修改转换逻辑!

运行后得到的结果和你想要的目标格式完全一致:

{
 'in': {'user1': {'age':10, 'state':'tn', 'pincode':1}, 'user2': {'age':11, 'state':'tx', 'pincode':2}},
 'eu': {'user3': {'age':12, 'state':'gh', 'pincode':3}, 'user4': {'age':13, 'state':'io', 'pincode':4}},
 'us': {'user5': {'age':14, 'state':'pi', 'pincode':5}, 'user6': {'age':15, 'state':'ew', 'pincode':6}}
}

内容的提问来源于stack exchange,提问作者rakesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:37:40