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

如何用Pandas内置方法替代循环转换多层嵌套字典(含列表)为DataFrame?

三层嵌套字典转指定DataFrame的Pandas优化方案

针对你这种三层嵌套字典+列表的结构,确实有比手动嵌套循环更高效的Pandas内置方法或优化写法,下面两种方案都能替代原循环,且效率更高:

方案一:Pandas链式内置方法组合

利用pd.json_normalize、melt和explode三个方法配合,完全通过Pandas内置操作实现转换:

import pandas as pd

data = {
   "etherA": {
      "vlanY": {
         "local": ['mac01', 'mac02'],
         "external": ['mac03', 'mac02']
      }
   },
   "etherB": {
      "vlanZ": {
         "local": ['mac06', 'mac09'],
         "external": ['mac01', 'mac02', 'mac03']
      }
   }
}

# 先将顶层结构转换为json_normalize可处理的列表格式
flat_data = [
    {"interface": iface, "vlan": vlan, **dyn_macs}
    for iface, vlans in data.items()
    for vlan, dyn_macs in vlans.items()
]

# 链式操作完成转换
df = (pd.json_normalize(flat_data)
      .melt(id_vars=['interface', 'vlan'], var_name='dyn', value_name='mac-address')
      .explode('mac-address')
      .reset_index(drop=True))

print(df)

输出结果和你预期完全一致:

interface   vlan       dyn mac-address
0    etherA  vlanY     local       mac01
1    etherA  vlanY     local       mac02
2    etherA  vlanY  external       mac03
3    etherA  vlanY  external       mac02
4    etherB  vlanZ     local       mac06
5    etherB  vlanZ     local       mac09
6    etherB  vlanZ  external       mac01
7    etherB  vlanZ  external       mac02
8    etherB  vlanZ  external       mac03

步骤说明:

  1. flat_data整理:把顶层的interface和vlan提取为键,将dyn类型的字典展开到同一层级,为json_normalize做准备;
  2. json_normalize:将嵌套字典转换为宽表结构,此时local和external是列,值为mac列表;
  3. melt:将宽表转为长表,把local/external列合并为dyn列,对应的mac列表转为mac-address列;
  4. explode:将mac-address列的列表元素拆分为单独行,最后重置索引。

方案二:列表推导式+DataFrame批量生成

如果追求最高效率,先通过Python列表推导式扁平化所有数据,再一次性生成DataFrame,这种写法比嵌套循环逐个添加行快得多(避免了Pandas逐行修改的性能损耗):

import pandas as pd

data = {
   "etherA": {
      "vlanY": {
         "local": ['mac01', 'mac02'],
         "external": ['mac03', 'mac02']
      }
   },
   "etherB": {
      "vlanZ": {
         "local": ['mac06', 'mac09'],
         "external": ['mac01', 'mac02', 'mac03']
      }
   }
}

# 用列表推导式直接生成所有行的记录
flat_records = [
    (iface, vlan, dyn_type, mac)
    for iface, vlans in data.items()
    for vlan, dyn_dict in vlans.items()
    for dyn_type, mac_list in dyn_dict.items()
    for mac in mac_list
]

# 批量生成DataFrame
df = pd.DataFrame(flat_records, columns=['interface', 'vlan', 'dyn', 'mac-address'])

这个方案的结果和方案一完全相同,但数据量越大,性能优势越明显——因为列表推导式是Python原生高效操作,且一次性创建DataFrame避免了多次修改的开销。

对比原循环的优势

你原来的df.loc[len(df)]逐行赋值的方式,每次都会触发DataFrame的内部结构调整,数据量较大时会非常缓慢。上面两种方案都是先将数据整理为扁平结构,再一次性生成DataFrame,效率至少提升一个数量级,且代码更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:17:51