You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Pandas无法处理超550条记录的DataFrame匹配任务?

解决Pandas对比大数据量Excel文件找唯一记录的问题

我需要从包含约4万条记录的Total.xlsx中,找出仅存在于该文件中的约4千条记录,对比对象是包含约3.6万条记录的Recent.xlsx。我原本使用的双重循环Pandas代码仅能处理最多550条记录,处理完整文件或超过500条记录的文件时无法正常运行,尝试分块处理也无效。

原代码

import pandas as pd

file1 = 'Total.xlsx'
df1 = pd.read_excel(file1)

file2 = 'Recent.xlsx'
df2 = pd.read_excel(file2)

non_matching_rows = []

for index1, row1 in df1.iterrows():
    row_matches = False
    
    for index2, row2 in df2.iterrows():
        if row1.equals(row2):
            row_matches = True
            break
    
    if not row_matches:
        non_matching_rows.append(row1)

non_matching_df = pd.DataFrame(non_matching_rows)

display(non_matching_df)
print(non_matching_df.count())

原代码的问题

这段代码的核心问题是双重逐行循环:

  • 时间复杂度为O(n*m),4万条记录乘以3.6万条记录意味着144亿次循环操作,完全超出合理计算时间范围。
  • iterrows()本身是低效率的遍历方式,无法利用Pandas的向量化运算优势,大数据量下会导致内存占用过高或直接卡死。

高效解决方案

以下两种方法均基于Pandas的向量化操作,能在几秒到几十秒内完成大数据量对比:

方法一:使用merge的匹配标记(推荐)

通过合并两个DataFrame并添加匹配状态标记,直接筛选仅存在于Total.xlsx的记录:

import pandas as pd

# 读取两个Excel文件
df_total = pd.read_excel('Total.xlsx')
df_recent = pd.read_excel('Recent.xlsx')

# 左连接合并,添加_merge列标记匹配状态
merged_df = df_total.merge(df_recent, how='left', indicator=True)

# 筛选仅存在于Total的记录,删除标记列
only_in_total = merged_df[merged_df['_merge'] == 'left_only'].drop(columns=['_merge'])

# 输出结果
display(only_in_total)
print(only_in_total.count())
  • 优势:完全基于Pandas的高效向量化合并逻辑,内存占用可控,处理4万+3.6万级别的数据毫无压力。

方法二:利用isin结合行元组集合

将Recent.xlsx的行转换为元组集合,通过集合快速判断Total.xlsx的行是否存在:

import pandas as pd

df_total = pd.read_excel('Total.xlsx')
df_recent = pd.read_excel('Recent.xlsx')

# 将Recent的所有行转换为元组,存入集合(集合的查询是O(1)时间复杂度)
recent_row_set = set(df_recent.apply(tuple, axis=1))

# 筛选Total中不在Recent集合里的行
only_in_total = df_total[~df_total.apply(tuple, axis=1).isin(recent_row_set)]

display(only_in_total)
print(only_in_total.count())
  • 注意:如果DataFrame包含非哈希able类型的列(如列表),此方法会报错,此时优先使用方法一。

分块处理的正确姿势(若内存不足)

如果Excel文件过大导致内存不足,可以分块读取Recent.xlsx并逐步筛选:

import pandas as pd

df_total = pd.read_excel('Total.xlsx')
# 标记所有行初始为未匹配
df_total['is_unique'] = True

# 分块读取Recent.xlsx,每次处理1万条
chunk_size = 10000
for chunk in pd.read_excel('Recent.xlsx', chunksize=chunk_size):
    # 找出当前块中与Total匹配的行
    matched = df_total.merge(chunk, how='inner')
    # 将匹配到的行标记为非唯一
    df_total.loc[df_total.index.isin(matched.index), 'is_unique'] = False

# 筛选仅存在于Total的行
only_in_total = df_total[df_total['is_unique']].drop(columns=['is_unique'])

display(only_in_total)
print(only_in_total.count())

内容的提问来源于stack exchange,提问作者Subhash-23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:48:40