3万行数据场景下,如何高效对比主DataFrame与控制DataFrame?
优化大数量级DataFrame的邮箱匹配逻辑
你的需求是检查主DataFrame(df)中的邮箱是否存在于控制DataFrame(df_controle)中,匹配则标记为'ja'。先看你提供的原代码:
import pandas as pd data={'Name':['Danny','Damny','Monny','Quony','Dimny','Danny'], 'Email':['danny@gmail.com','danny@gmail.com','monny@gmail.com','quony@gmail.com','danny@gmail.com','danny@gmail.com']} df=pd.DataFrame(data) data1={'Name':['Danny','Monny','Quony'], 'Email':['danny@gmail.com','monny@gmail.com','quony@gmail.com']} df_controle=pd.DataFrame(data1) df['email_found_in_control_list']=None col_email=df_controle.columns.get_loc("Email") row_count=len(df.index) for i in range(0,row_count): emailadres=df['Email'][i] for k in range(0, col_email): if emailadres==df_controle.iloc[k,col_email]: df['email_found_in_control_list'][i] = 'ja' df.head()
原代码存在的问题
- 效率极低:两层Python循环遍历行,时间复杂度为O(n*m),当df有3万行时运行速度会非常慢——pandas的核心优势是矢量化操作,应避免手动遍历行。
- 逻辑错误:内层循环
range(0, col_email)中,col_email是Email列的索引(此处为1),循环仅执行k=0,相当于只检查df_controle的第一行,会漏掉其他匹配项。 - 数据修改风险:
df['email_found_in_control_list'][i]属于链式索引,可能触发SettingWithCopyWarning,导致数据修改不生效或不稳定。
优化实现方案
用pandas内置的矢量化方法替代循环,效率能提升几个数量级:
import pandas as pd # 构造数据 data={'Name':['Danny','Damny','Monny','Quony','Dimny','Danny'], 'Email':['danny@gmail.com','danny@gmail.com','monny@gmail.com','quony@gmail.com','danny@gmail.com','danny@gmail.com']} df=pd.DataFrame(data) data1={'Name':['Danny','Monny','Quony'], 'Email':['danny@gmail.com','monny@gmail.com','quony@gmail.com']} df_controle=pd.DataFrame(data1) # 提取控制列表的邮箱集合(去重后查找效率更高) control_email_set = set(df_controle['Email']) # 批量标记匹配结果 df['email_found_in_control_list'] = df['Email'].isin(control_email_set).map({True: 'ja', False: None}) print(df.head())
方案说明
isin()是pandas的矢量化方法,底层用C实现,能一次性完成所有行的匹配检查,比Python循环快得多。- 把控制邮箱转成集合
set,可将单次查找的时间复杂度从O(m)降到O(1),进一步提升大数量级数据下的效率。 - 如果需要忽略大小写匹配,可以先统一转换邮箱格式:
df['email_found_in_control_list'] = df['Email'].str.lower().isin(df_controle['Email'].str.lower()).map({True: 'ja', False: None})
内容的提问来源于stack exchange,提问作者Rohit Nirmal
相关产品推荐
相关产品推荐

