如何用Pandas高效替代非数值列的嵌套循环?
高效替代嵌套循环的Pandas匹配方案
原嵌套循环的问题在于逐元素遍历的时间复杂度是O(n*m),数据量稍大就会慢到无法忍受,直接用Pandas的矢量化操作可以解决这个问题,以下是两种高效方案:
方案一:使用merge左连接(推荐,适合多字段匹配)
直接通过merge做左连接,再处理缺失值,一步到位:
import pandas as pd # 示例数据 df1 = pd.DataFrame({ 'name': ['John', 'Mary', 'Sally', 'Doe', 'July'], 'rpm': [1500, 1400, 300, 700, 1000], 'power': ['high+', 'high-', 'low-', 'medium-', 'medium+'] }) df2 = pd.DataFrame({ 'name': ['Peter', 'Sally', 'Micky', 'Sally', 'July', 'Bob'], 'age': [77, 44, 22, 34, 50, 20] }) # 左连接匹配name字段 merged_df = df2.merge(df1, on='name', how='left') # 匹配失败时rpm设为0 merged_df['rpm'] = merged_df['rpm'].fillna(0) # power字段匹配失败保留缺失值(即NA) print(merged_df)
执行后会直接得到你要的结果:
name age rpm power 0 Peter 77 0.0 NaN 1 Sally 44 300.0 low- 2 Micky 22 0.0 NaN 3 Sally 34 300.0 low- 4 July 50 1000.0 medium+ 5 Bob 20 0.0 NaN
(注:Pandas中用NaN表示缺失值,对应你需求里的NA,如果需要显示为字符串"NA",可以再加一行merged_df['power'] = merged_df['power'].fillna('NA'))
方案二:使用map映射(适合单字段快速匹配)
如果只需要匹配个别字段,用map更简洁:
# 从df1构建name到对应字段的映射字典 rpm_map = df1.set_index('name')['rpm'].to_dict() power_map = df1.set_index('name')['power'].to_dict() # 给df2添加匹配后的字段 df2['rpm'] = df2['name'].map(rpm_map).fillna(0) df2['power'] = df2['name'].map(power_map)
这个方法同样是矢量化操作,速度远快于嵌套循环,结果和方案一一致。
为什么这两种方法更快?
Pandas的merge和map都是基于底层优化的矢量化操作,使用哈希匹配或批量查找的逻辑,时间复杂度仅为O(n + m)或O(n log m),而嵌套循环是O(n*m),当数据量超过千级时,速度差距会达到几十甚至上百倍,同时还能避免链式索引带来的SettingWithCopyWarning问题。
内容的提问来源于stack exchange,提问作者Bold Ganbaatar
相关产品推荐
相关产品推荐

