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

为何使用multiprocessing.dummy实现的抽样打标函数未对全部col_2取值生效

问题原因分析
  • 核心原因是pandas DataFrame 不是线程安全对象,你在多线程中并发修改全局变量df2时没有加同步锁,多个线程的写操作会出现冲突,导致b、c对应的修改被覆盖或者直接丢失,只有最先完成的a的修改保留了下来。
  • 另外你代码中没有显式调用P.close()和P.join()回收线程池资源,虽然map方法本身是阻塞的,但极端情况下也可能出现主线程提前读取未完成修改的df2的问题。
更优的实现方案

这个需求完全不需要引入多线程,直接用pandas自带的groupby操作就能更简洁的实现,没有并发冲突风险:

import pandas as pd
import numpy as np

data = np.array([(3, 'a'), (2, 'a'), (1, 'b'), (0, 'c'), (2, 'c'), (3, 'c')],
                dtype=[('col_1', 'i4'), ('col_2', 'U1')])
df = pd.DataFrame.from_records(data)
df['batch'] = 0

def process_group(g):
    # 每组最多抽2行
    sample_num = min(2, len(g))
    sampled = g.sample(sample_num)
    sampled['batch'] = range(1, sample_num + 1)
    return sampled

df2 = df.groupby('col_2', group_keys=False).apply(process_group).reset_index(drop=True)

如果一定要使用多线程实现,需要避免在子线程中直接修改全局DataFrame,改为子线程返回修改结果,主线程统一写入:

import pandas as pd
import numpy as np
import os
from multiprocessing import dummy
from random import sample

core = os.cpu_count()
P = dummy.Pool(processes = core)

data = np.array([(3, 'a'), (2, 'a'), (1, 'b'), (0, 'c'), (2, 'c'), (3, 'c')],
                dtype=[('col_1', 'i4'), ('col_2', 'U1')])
df = pd.DataFrame.from_records(data)
df['batch'] = 0
df2 = df.copy()

def func(c):
    idx = df.col_2 == c
    pop = list(df[idx].index)
    m = min(2, len(pop))
    r = sample(pop, m)
    return zip(r, range(1, m+1))

results = P.map(func, ['a', 'b', 'c'])
# 回收线程池
P.close()
P.join()

# 主线程统一写入修改
for modify_items in results:
    for idx, batch_val in modify_items:
        df2.loc[idx, 'batch'] = batch_val

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 20:36:01