如何从JSON类型Series为DataFrame新增列并规整数据格式
问题描述
现有如下结构的DataFrame:
import pandas as pd data = { 'network': ['vpc-1', 'vpc-1', 'vpc-1', 'vpc-1'], 'allowed': [ [{'IPProtocol': 'tcp', 'ports': ['53']}], [{'IPProtocol': 'tcp', 'ports': ['22', '3389']}], [{'IPProtocol': 'icmp'}, {'IPProtocol': 'sctp'}], [{'IPProtocol': 'all'}] ] } df = pd.DataFrame(data)
打印输出为:
network allowed 0 vpc-1 [{'IPProtocol': 'tcp', 'ports': ['53']}] 1 vpc-1 [{'IPProtocol': 'tcp', 'ports': ['22', '3389']}] 2 vpc-1 [{'IPProtocol': 'icmp'}, {'IPProtocol': 'sctp'}] 3 vpc-1 [{'IPProtocol': 'all'}]
曾尝试用apply(pd.Series)展开allowed列,但得到多列嵌套字典的格式,不符合需求。期望得到如下格式:
network allowed.IPProtocol allowed.ports 0 vpc-1 tcp 53 1 vpc-1 tcp 22, 3389 2 vpc-1 icmp, sctp - 3 vpc-1 all -
解决方案
通过拆分列表→解析字典→分组聚合三步即可实现:
# 1. 将allowed列的列表拆分为多行,保留原行的network关联 df_exploded = df.explode('allowed', ignore_index=False) # 2. 将字典列解析为独立字段 df_parsed = df_exploded['allowed'].apply(pd.Series) # 3. 处理ports字段:列表转逗号分隔字符串,无端口或协议为all时填'-' df_parsed['ports'] = df_parsed.apply( lambda row: ', '.join(row['ports']) if 'ports' in row and row['ports'] else '-', axis=1 ) # 4. 按network分组,聚合IPProtocol为逗号拼接字符串,ports取对应唯一值 result = df_parsed.groupby(df_exploded['network']).agg( **{ 'allowed.IPProtocol': ('IPProtocol', ', '.join), 'allowed.ports': ('ports', lambda x: x.unique()[0] if len(x.unique()) == 1 else '-') } ).reset_index()
代码说明
explode('allowed'):把每个列表内的字典拆成单独行,让每个字典对应一行,便于后续解析。apply(pd.Series):将字典的键转换为列,值自动填充到对应位置。- 处理
ports时,判断字段是否存在且有有效值,否则用'-'替代;all协议的行本身无ports键,会自动填充'-'。 - 分组聚合时,把同一
network下的IPProtocol用逗号拼接;ports取唯一值(同一组内的ports要么一致,要么都是'-')。
运行上述代码后,即可得到期望的目标格式。
内容的提问来源于stack exchange,提问作者Soomin Eom
相关产品推荐
相关产品推荐

