如何高效基于含键值对的地址列拆分生成结构化地址新列?
如何高效基于含键值对的地址列拆分生成结构化地址新列?
嘿,这个问题我之前也碰到过,循环五次遍历整个DataFrame确实既麻烦又低效,尤其是数据量大的时候,速度会拖得很慢。其实用pandas的内置方法就能一次性搞定,不用写那些重复的循环代码,我给你捋捋具体怎么做:
核心思路
咱们先把所有地址列打包成每行的字典列表,然后把这些字典展开成结构化的键值对,最后通过透视把地址项转换成单独的列,再和原数据的基础信息合并就搞定了。
完整代码实现
import pandas as pd # 还原你的原始DataFrame data = [['Tom', 10, 'Business Analyst',{'AddressItemName': 'StreetNo', 'AddressItemValue': '12345'},{'AddressItemName': 'StreetName', 'AddressItemValue': 'Broadway'},{'AddressItemName': 'City', 'AddressItemValue': 'New York'},{'AddressItemName': 'State', 'AddressItemValue': 'NY'},{'AddressItemName': 'Zip', 'AddressItemValue': '12345'}], ['David', 10, 'Data Analyst',{'AddressItemName': 'Zip', 'AddressItemValue': '23456'},{'AddressItemName': 'City', 'AddressItemValue': 'Atlanta'},{'AddressItemName': 'StreetNo', 'AddressItemValue': '11111'},{'AddressItemName': 'StreetName', 'AddressItemValue': 'Main St'},{'AddressItemName': 'State', 'AddressItemValue': 'GA'}], ['Nick', 10, 'Data Engineer',{'AddressItemName': 'State', 'AddressItemValue': 'NY'},{'AddressItemName': 'Zip', 'AddressItemValue': '12345'},{'AddressItemName': 'StreetNo', 'AddressItemValue': '34567'},{'AddressItemName': 'StreetName', 'AddressItemValue': 'Broadway'},{'AddressItemName': 'City', 'AddressItemValue': 'New York'}]] df = pd.DataFrame(data, columns=['Name', 'Dept', 'JobType', 'Address1', 'Address2', 'Address3', 'Address4', 'Address5']) # 步骤1:把所有地址列合并成每行的字典列表 address_cols = df.filter(like='Address') # 筛选出所有地址列 df['address_list'] = address_cols.apply(list, axis=1) # 每行的5个地址字典拼成一个列表 # 步骤2:展开字典列表,转换成结构化的键值对DataFrame address_df = pd.DataFrame( df['address_list'].explode().tolist(), index=df['address_list'].explode().index # 保留原行索引,方便后续合并 ) # 步骤3:透视数据,把AddressItemName转成列,AddressItemValue作为对应的值 pivoted_address = address_df.pivot( index=address_df.index, columns='AddressItemName', values='AddressItemValue' ).reset_index(drop=True) # 重置索引,和原数据对齐 # 步骤4:合并原数据的基础列和透视后的地址列 result_df = pd.concat([df[['Name', 'Dept', 'JobType']], pivoted_address], axis=1) print(result_df)
代码解释
- 步骤1:用
filter(like='Address')快速筛选出所有地址列,再用apply(list, axis=1)把每行的5个地址字典打包成一个列表,这样每行就对应一个完整的地址字典集合。 - 步骤2:
explode()把列表拆成多行,每个字典单独占一行,同时保留原数据的索引;然后用tolist()把字典转换成DataFrame的两列(AddressItemName和AddressItemValue)。 - 步骤3:
pivot()函数把地址项名称转成列名,对应的地址值填充到列里,这样就得到了每行对应的结构化地址列。 - 步骤4:用
concat()把原数据的基础信息(Name、Dept、JobType)和结构化的地址列合并,就得到了你想要的最终结果。
为什么这个方法更好?
这个方法全程用pandas的向量化操作,不需要手动循环遍历每行每列,不仅代码更简洁,而且处理大数据集的时候速度会比循环快很多——毕竟pandas的内置方法都是经过优化的,比Python原生循环效率高得多。
备注:内容来源于stack exchange,提问作者Sanjeev
相关产品推荐
相关产品推荐

