Pandas循环处理小DataFrame正常,大数据集卡顿如何优化?
哇,7万条数据用iterrows()跑40小时,这确实太折磨人了!我来帮你把速度提上去,顺便聊聊哈希的问题~
问题根源:为什么你的代码这么慢?
- 你用了
iterrows()逐行遍历,这是Pandas里效率最低的操作之一——它是Python级别的循环,每次迭代都有额外的开销。 - 更糟的是,每处理一个邮编,你都要完整遍历一遍邮编表
zc,时间复杂度直接拉到O(n*m)(n是你的7万条数据,m是邮编表的行数),这就是为什么预估时间会超40小时。
最优提速方案:用Pandas的merge做矢量化匹配
Pandas的merge是底层用C实现的矢量化操作,专门处理这类表连接场景,速度能提升几个数量级。针对你提到的三种邮编类型(有效数字、非数字字符串、无效数字字符串),我们可以这样处理:
步骤1:预处理两个表的邮编字段
先统一字段类型,避免匹配时的类型冲突:
import numpy as np import pandas as pd # 加载数据 df = pd.read_csv('customer_April2018.csv', encoding='latin-1') zc = pd.read_csv('us_postal_codes.csv', encoding='latin-1') # 把邮编表的ZipCode转成数值类型(方便和用户表的邮编匹配) zc['ZipCode_num'] = zc['ZipCode'].astype(int) # 处理用户表的邮编:能转成数字的转成数值,不能转的设为NaN df['ZipCode_clean'] = pd.to_numeric(df['ZipCode'], errors='coerce')
步骤2:用merge批量匹配县份
这一步会一次性完成所有匹配,完全替代低效的循环:
# 左连接:保留用户表所有行,匹配到的填充County,没匹配到的留空 df_merged = df.merge( zc[['ZipCode_num', 'County']], left_on='ZipCode_clean', right_on='ZipCode_num', how='left' ) # 把没匹配到的情况(包括非数字、无效数字邮编)统一设为'No County' df_merged['County'] = df_merged['County'].fillna('No County') # 清理临时字段并保存结果 df_merged.drop(columns=['ZipCode_clean', 'ZipCode_num'], inplace=True) df_merged.to_csv('join_test.csv', index=False)
关于哈希函数的疑问:你不需要自己实现!
其实Pandas的merge在默认情况下(当连接字段是数值/字符串时),已经使用了哈希连接的优化策略——它会先对连接字段构建哈希表,然后一次性完成匹配,这正是处理大规模数据的最优方案。自己手动实现哈希函数不仅没必要,还可能因为优化不到位反而变慢,直接用Pandas内置的merge就够了。
额外小提示:如果邮编带前导零
如果你的有效邮编包含前导零(比如'00123'),转成数值会丢失前导零,这时候应该把两个表的邮编都转成字符串来匹配:
# 统一转成5位字符串,保留前导零 zc['ZipCode_str'] = zc['ZipCode'].astype(str).str.zfill(5) df['ZipCode_str'] = df['ZipCode'].str.zfill(5) # 用字符串做连接匹配 df_merged = df.merge( zc[['ZipCode_str', 'County']], left_on='ZipCode_str', right_on='ZipCode_str', how='left' )
这样处理完,7万条数据应该在几秒到几十秒内就能完成,完全不用等40小时啦!
内容的提问来源于stack exchange,提问作者user40551
相关产品推荐
相关产品推荐

