Python Pandas中是否存在比df.nunique()更快的DataFrame唯一值计数方法?
大数据集下
df.nunique()的性能优化方案 我发现df.nunique()的耗时大致随数据量线性增长,想了解当数据量增大时是否有更优的解决方案?以下是示例代码及测试结果,盼提出更快的实现思路!
示例代码
import numpy as np import pandas as pd def createList(r1, r2): """ 创建指定范围的数值列表 示例: createList(1,3) == [1, 2, 3] """ return np.arange(r1, r2+1, 1) sample_df = pd.DataFrame( data = { 'a' : createList(1, 50_000_000), 'b' : createList(1, 50_000_000), 'c' : createList(1, 50_000_000), 'd' : createList(1, 50_000_000), 'e' : createList(1, 50_000_000), 'f' : createList(1, 50_000_000), 'g' : createList(1, 50_000_000), } ) sample_df.nunique()
测试结果
在Jupyter Notebook中使用%%timeit测试的耗时如下:
sample_df.nunique() # 5000万行数据,10.5 s ± 3.05 s per loop (7次运行的均值±标准差,每次1循环) sample_df.nunique() # 1亿行数据,21.2 s ± 6.16 s per loop (7次运行的均值±标准差,每次1循环)
优化思路
直接用Numpy底层方法加速:
Pandas的nunique()带有封装开销,直接调用Numpy的np.unique逐列处理,能减少额外消耗,数值型数据场景下可提速10%-30%:result = {col: len(np.unique(sample_df[col].values)) for col in sample_df.columns}分块处理(内存友好):
若数据集超出内存容量,可分块读取数据,用集合累加每块的唯一值,最后合并统计总数:chunk_size = 10_000_000 unique_counts = {col: set() for col in sample_df.columns} # 假设数据来自CSV文件,按块读取 for chunk in pd.read_csv('large_data.csv', chunksize=chunk_size): for col in chunk.columns: unique_counts[col].update(chunk[col].unique()) # 最终统计结果 result = {col: len(vals) for col, vals in unique_counts.items()}多核心并行计算(Dask):
利用Dask拆分数据集到多个CPU核心并行处理,超大规模数据场景下性能提升接近线性(取决于核心数):import dask.dataframe as dd dask_df = dd.from_pandas(sample_df, npartitions=4) # 根据CPU核心数设置分区数 result = dask_df.nunique().compute()特定数据类型针对性优化:
- 非负整数列:用
np.bincount替代unique,速度更快:result = {col: np.count_nonzero(np.bincount(sample_df[col].values)) for col in sample_df.columns} - 字符串列:先通过
pd.factorize将字符串编码为整数,再统计唯一值,比直接处理字符串高效。
- 非负整数列:用
内容的提问来源于stack exchange,提问作者trey hannam
相关产品推荐
相关产品推荐

