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

Python 3.6.4中使用df.duplicated()报MemoryError的问题求助

解决Pandas中df.duplicated()触发MemoryError的问题

我之前处理过类似的大内存数据问题,咱们来拆解一下原因和解决方案:

问题根源

你用分块加载后concat得到了完整的DataFrame,但df.duplicated()需要对所有列的所有行做逐行比较,这会在内存中生成大量临时数据——15万行×208列的数据量,加上比较过程中的额外内存开销,很容易触发内存不足的错误。

解决方案推荐

1. 分块阶段先去重,再合并(最推荐)

与其等到所有数据加载完再处理重复,不如在每个分块加载时就先去掉内部重复,这样能大幅减少最终合并后DataFrame的大小,后续的重复检查压力也会小很多:

myList = []
for chunk in pd.read_csv(filename, header=0, low_memory=False, chunksize=20000):
    # 先移除当前分块内的重复行
    chunk = chunk.drop_duplicates()
    myList.append(chunk)

# 合并分块后,再处理跨分块的重复行
dfMain = pd.concat(myList, axis=0).drop_duplicates()
dfMain.index.name = 'Index'
print(dfMain.shape)

这个方法能在数据加载的过程中就“瘦身”,从源头减少内存占用。

2. 用行哈希替代全列比较(保留所有行时使用)

如果需要保留所有行只是标记重复,咱们可以先给每行计算一个唯一哈希值(内存占用远小于整行数据),再通过哈希值判断重复:

def compute_row_hash(chunk):
    # 计算每行的哈希值,pandas内置方法高效且稳定
    return pd.util.hash_pandas_object(chunk, index=False)

all_hashes = []
myList = []
for chunk in pd.read_csv(filename, header=0, low_memory=False, chunksize=20000):
    myList.append(chunk)
    # 计算当前分块的行哈希
    all_hashes.append(compute_row_hash(chunk))

# 合并数据和哈希值
dfMain = pd.concat(myList, axis=0)
dfMain['row_hash'] = pd.concat(all_hashes, axis=0).values

# 基于哈希值判断重复,内存开销大幅降低
duplicated_mask = dfMain.duplicated(subset='row_hash')

如果担心哈希碰撞,可以对标记为重复的行再做一次全列精确校验,不过绝大多数场景下哈希值的唯一性足够可靠。

3. 优化数据类型,降低整体内存占用

你的DataFrame有208列,很多列的类型可能可以进一步压缩:

  • 数值列:把int64/float64向下转换为更小的类型(比如int32/float32,只要数据范围允许)
  • 字符串列:如果唯一值占比低(比如低于50%),转换成category类型,内存占用会大幅减少

代码示例:

def optimize_chunk_dtypes(chunk):
    # 优化数值列
    for col in chunk.select_dtypes(include=['int64']).columns:
        chunk[col] = pd.to_numeric(chunk[col], downcast='integer')
    for col in chunk.select_dtypes(include=['float64']).columns:
        chunk[col] = pd.to_numeric(chunk[col], downcast='float')
    # 优化字符串列
    for col in chunk.select_dtypes(include=['object']).columns:
        unique_ratio = len(chunk[col].unique()) / len(chunk[col])
        if unique_ratio < 0.5:
            chunk[col] = chunk[col].astype('category')
    return chunk

myList = []
for chunk in pd.read_csv(filename, header=0, low_memory=False, chunksize=20000):
    chunk = optimize_chunk_dtypes(chunk)
    myList.append(chunk)

dfMain = pd.concat(myList, axis=0)
dfMain.index.name = 'Index'
# 现在再执行duplicated()就不会轻易爆内存了
duplicated_mask = dfMain.duplicated()

小提示

你可以先执行dfMain.memory_usage(deep=True).sum()查看优化前后的内存占用,能直观看到效果。

内容的提问来源于stack exchange,提问作者Jerry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:30:39