如何加速DataFrame循环并解决SettingWithCopyWarning警告?
这问题太典型了——用iterrows循环10万行肯定慢到离谱,而且那个SettingWithCopyWarning也是Pandas新手常踩的坑。我给你两个层面的解决方案:先解决核心的速度问题,再顺便把警告干掉(其实用高效方案的话警告直接就消失了)。
一、核心加速:用pd.merge_asof替代逐行循环
这绝对是最优解,Pandas专门为「按最近键匹配」这种场景设计了merge_asof,性能比逐行循环高几个数量级,而且代码简洁到爆炸。
原理
merge_asof会先对两个DataFrame按匹配键(这里是timestamp_milli)排序,然后用二分查找的方式快速找到每个左表行对应的右表最近匹配行,还能设置时间差容忍度(就是你要的±5ms)。时间复杂度是O(n log n + m log m)(排序的时间),对比原代码O(n*m)的暴力循环,10万行的话速度能提升几百甚至几千倍。
代码实现
# 第一步:必须按时间戳排序(merge_asof的硬性要求) df_sorted = df.sort_values("timestamp_milli").reset_index(drop=True) df2_sorted = df2.sort_values("timestamp_milli").reset_index(drop=True) # 第二步:用merge_asof做最近匹配,限制±5ms的时间差 merged_df = pd.merge_asof( left=df_sorted, right=df2_sorted, on="timestamp_milli", direction="nearest", # 找最近的匹配行 tolerance=5 # 只匹配时间差在±5ms内的行 ) # 第三步:提取你需要的结果列表 pressure = merged_df["pressure"].tolist() acceleration = merged_df["acceleration_z"].tolist()
补充说明
- 如果df中某行在df2的±5ms范围内没有匹配,
merged_df里对应的acceleration_z会是NaN,你可以根据需求用fillna()处理或者过滤掉这些行。 - 原代码中如果有多个行的时间差都是最小值,会把所有这些行的加速度都加入列表;而
merge_asof的direction='nearest'在这种情况下只会取最后一个匹配的行。如果你的业务场景必须保留所有最小时间差的匹配,可以留言,我再给你补充对应的处理逻辑。
二、如果一定要保留循环逻辑:解决SettingWithCopyWarning
警告的根源是df_temp = df2[mask]得到的是df2的视图(不是独立副本),Pandas担心你会意外修改原df2的数据,所以抛出警告。解决方法很简单:显式创建副本:
把原代码里的:
df_temp = df2[mask]
改成:
df_temp = df2[mask].copy()
这样df_temp就是独立的DataFrame,修改它的列就不会触发警告了。不过还是要强调:这种方法只是解决了警告,速度慢的问题依然存在,10万行的循环还是会跑很久,强烈不推荐。
内容的提问来源于stack exchange,提问作者machinery
相关产品推荐
相关产品推荐

