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

如何使用numba加速pandas差异统计for循环并解决相关报错

报错根因
  • 你遇到的AssertionError是Numba的nopython模式无法编译代码中的不支持特性导致的:该模式完全不支持Pandas的各类API(包括applymap、loc、布尔索引、unique()等),同时你用到的lambda表达式、列表推导式内调用set.add、全局DataFrame引用、tqdm调用都是nopython模式无法识别的语法,编译阶段出现变量冲突触发了报错。
  • 代码本身还存在逻辑漏洞:循环中重复调用unique()产生冗余计算、用于存储差异列的s列表没有每次重置导致不同分组的结果互相污染、函数内部直接读取全局变量df不符合Numba的传参规则。
优先方案:不用Numba的原生Pandas实现

你的需求可以直接通过Pandas内置的groupby聚合实现,所有运算都走C层优化,性能远高于你手写的Python循环加Numba的方案:

import pandas as pd

# 全列转字符串
df = df.astype(str)
# 定义需要检查差异的列:排除分组用的两个字段
check_cols = [col for col in df.columns if col not in ["client_cookie_id", "OS_name"]]

def get_diff_columns(group):
    # 分组行数小于2时无差异
    if len(group) < 2:
        return []
    # 统计每列的唯一值数量,大于1说明存在差异
    return [col for col in check_cols if group[col].nunique() > 1]

# 按client_cookie_id和OS_name分组计算差异列
group_result = df.groupby(["client_cookie_id", "OS_name"]).apply(get_diff_columns).to_dict()

# 按client_cookie_id汇总所有OS分组下的差异列
final_dict = {}
for (cid, os_name), diff_cols in group_result.items():
    if cid not in final_dict:
        final_dict[cid] = set()
    final_dict[cid].update(diff_cols)
# 转换为列表格式
final_dict = {k: list(v) for k, v in final_dict.items()}
可选方案:必须使用Numba的正确写法

如果数据量极大确实需要Numba加速,必须先把Pandas对象转换为Numba支持的numpy数组传入,不能在Numba函数内部操作Pandas实例:

import pandas as pd
import numpy as np
from numba import jit

# 预处理:将所有分类字段和待比较值编码为整数(Numba处理整数效率远高于字符串)
cid_codes, cid_uniques = pd.factorize(df["client_cookie_id"])
os_codes, os_uniques = pd.factorize(df["OS_name"])
val_array = np.vstack([pd.factorize(df[col])[0] for col in check_cols]).T
col_name_array = np.array(check_cols)

@jit(nopython=True)
def calc_diff_columns(cid_codes, os_codes, val_array, col_name_array, cid_uniques):
    res = dict()
    max_cid = cid_codes.max() + 1
    max_os = os_codes.max() + 1
    for cid_idx in range(max_cid):
        cid_mask = cid_codes == cid_idx
        diff_set = set()
        for os_idx in range(max_os):
            group_mask = cid_mask & (os_codes == os_idx)
            row_indexes = np.where(group_mask)[0]
            if len(row_indexes) < 2:
                continue
            # 逐列检查值是否全部相同
            for col_idx in range(val_array.shape[1]):
                col_vals = val_array[row_indexes, col_idx]
                if not (col_vals == col_vals[0]).all():
                    diff_set.add(col_name_array[col_idx])
        res[cid_uniques[cid_idx]] = list(diff_set)
    return res

final_dict = calc_diff_columns(cid_codes, os_codes, val_array, col_name_array, cid_uniques)
注意事项
  • Numba的nopython模式不支持tqdm,需要进度条只能关闭nopython模式,或者在外层逻辑中添加
  • 所有需要在Numba函数中使用的数据必须通过参数传入,不能引用全局变量
  • 尽量不要在Numba中直接处理字符串,提前编码为整数可以让性能提升数十倍

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:06:06