是否有比 df.nunique() 更好/更快的方法来查找数据帧的唯一值计数? (Python 熊猫)

问题描述 投票:0回答:2

我注意到 df.nunique() 大致随数据大小线性缩放。我想知道随着数据大小的增加是否有更好的解决方案?这是一个例子,如果您能想出更快的方法,请告诉我!

import numpy as np
import pandas as pd

def createList(r1, r2):
    """ creates a list of values given a range.
    ex. 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 笔记本中运行 %%timeit 时,这是我得到的时间

sample_df.nunique() # with 50_000_000, 10.5 s ± 3.05 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

sample_df.nunique() # with 100_000_000, 21.2 s ± 6.16 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
python python-3.x pandas dataframe numpy
2个回答
0
投票

这种特殊情况下,我发现这样更快:

sample_df.apply(lambda S: len(np.unique(S.values)))

而且会更快,例如:

In [16]: sample_df = pd.DataFrame(
    ...:     data = {
    ...:         'a' : np.arange(1, 50_000_000+1),
    ...:         'b' : np.arange(1, 50_000_000+1),
    ...:         'c' : np.arange(1, 50_000_000+1),
    ...:         'd' : np.arange(1, 50_000_000+1),
    ...:         'e' : np.arange(1, 50_000_000+1),
    ...:         'f' : np.arange(1, 50_000_000+1),
    ...:         'g' : np.arange(1, 50_000_000+1),
    ...:     }
    ...: )

In [17]: %timeit sample_df.nunique()
25.4 s ± 919 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [18]: %timeit sample_df.apply(lambda S: len(np.unique(S.values)))
6.37 s ± 63.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

0
投票

使用 np.array_split 拆分数据帧并使用多处理在可用 CPU 数量之间拆分任务是我当前使用的更快的方法。

import multiprocessing as mp

# Define the function to be executed by each CPU
def process_data(data):
    # Process the data here
    # ...
    processed_data = data.nunique(axis=1)
    return processed_data 

# split your dataframe
dfs = np.array_split(df, mp.cpu_count())


with mp.Pool(processes=mp.cpu_count()) as pool:
        combs_uniques = pool.map(process_data, dfs)
© www.soinside.com 2019 - 2024. All rights reserved.