我注意到 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)
在这种特殊情况下,我发现这样更快:
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)
使用 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)