大体积DataFrame筛选多列值全同行及多列子集复用的提速方案咨询
优化方案
1. 替换nunique为直接等值比较(性能提升10~100倍,无额外依赖)
nunique需要逐行统计所有唯一值,开销极高。你的需求仅需要判断行内所有值相等,直接和该行第一列比较即可,用numpy向量化操作实现:
# 先定义你要筛选的列子集 cols = ['Q4_1a_1', 'Q4_1a_2', 'Q4_1a_3', 'Q4_1a_4', 'Q4_1a_5', 'Q4_1a_6'] # 生成布尔掩码:行内所有元素和第一个元素相等则为True mask = (dfSPSSstudent[cols].to_numpy() == dfSPSSstudent[cols[0]].to_numpy()[:, None]).all(axis=1) # 筛选结果 df_filtered = dfSPSSstudent[mask]
如果需要兼容NaN(将全NaN行判定为相等),调整mask逻辑即可:
arr = dfSPSSstudent[cols].to_numpy() mask = (arr == arr[:, [0]] | (np.isnan(arr) & np.isnan(arr[:, [0]]))).all(axis=1)
2. 多组列子集批量操作的预优化
如果需要反复对不同列子集执行该操作,提前做两个预处理减少重复开销:
- 提前将整个DataFrame转为numpy数组存储,避免每次切片重复做类型转换
- 提前把所有列子集的列名转为数值索引,避免重复做列名查找
# 预转换全量数据为numpy数组 full_arr = dfSPSSstudent.to_numpy() # 预生成列名到索引的映射 col_to_idx = {col: i for i, col in enumerate(dfSPSSstudent.columns)} # 之后处理任意列子集时直接调用即可 def get_same_rows_mask(cols): idx = [col_to_idx[c] for c in cols] sub_arr = full_arr[:, idx] return (sub_arr == sub_arr[:, [0]]).all(axis=1)
3. 超大数据量可选Numba JIT加速(性能再提升3~10倍)
如果你的DataFrame行数在千万级以上,可以用Numba编译自定义函数进一步降低numpy的广播开销:
import numpy as np import numba @numba.njit(parallel=True) # 开并行进一步提速 def all_same_mask(arr): n_rows, n_cols = arr.shape res = np.ones(n_rows, dtype=np.bool_) for i in numba.prange(n_rows): first = arr[i, 0] for j in range(1, n_cols): if arr[i, j] != first: res[i] = False break return res # 调用方式 mask = all_same_mask(dfSPSSstudent[cols].to_numpy())
内容的提问来源于stack exchange,提问作者fredooms
相关产品推荐
相关产品推荐

