[英]Number of Unique values in Dask-Dataframe columns
我从 csv 文件中读取了一个 Dask Dataframe,其中包含大约 100 万条记录和 120 个特征/列,我想计算每列中唯一值的数量。 我可以清楚地使用 for 循环分别为每一列执行此操作:
from dask import dataframe as dd
dask_df = dd.read_csv("train.csv")
for column in dask_df.columns:
print(dask_df[col].nunique().compute())
但是每次迭代的计算都非常昂贵(我花了大约 40 分钟,3 个节点集群有 5 个工作人员,每个工作人员有 2GB 内存和 2 个 vcore),所以有没有一种方法可以让我获得每列数据的唯一值-框架? 我已经尝试过dask_df.describe() api,但它只为字符串类型提供唯一值。 任何帮助表示赞赏,在此先感谢!
我不知道这是否是最快的解决方案,但您可以使用.melt()
来.melt()
数据.groupby()
列的.groupby()
,然后在变量列上使用.groupby()
来计算每个组中的唯一值以获得显着的性能对每列解决方案的改进:
dd.read_csv('test.csv').melt().groupby('variable')['value'].nunique().compute()
让我们生成一些随机整数数据并保存为 csv:
import numpy as np
import pandas as pd
from dask import dataframe as dd
nrows = 10000
ncols = 120
rng = np.random.default_rng(seed=1)
random_data = rng.integers(low=0, high=nrows/2, size=(nrows,ncols))
pd.DataFrame(data=random_data).add_prefix('col_').to_csv('test.csv', index=False)
我们使用以下两个函数进行性能评估:
def nunique_per_column():
dask_df = dd.read_csv('test.csv')
counts = []
for col in dask_df.columns:
counts.append(dask_df[col].nunique().compute())
return pd.Series(counts, index=dask_df.columns)
def melt_groupby_nunique():
return dd.read_csv('test.csv').melt().groupby('variable')['value'].nunique().compute()
首先检查两个函数是否计算相同的结果:
pd.testing.assert_series_equal(nunique_per_column().sort_index(),
melt_groupby_nunique().sort_index(),
check_names=False)
函数和示例数据上的%timeit
在我的机器上产生以下输出:
%timeit nunique_per_column()
17.5 s ± 216 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit melt_groupby_nunique()
1.78 s ± 576 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
这是另一种解决方法,其中每列的唯一值的数量都是一次计算的,从而有更多的优化机会:
import random
import pandas
import dask
import dask.dataframe as dd
df = pandas.DataFrame({
"x": [random.randint(0,100) for _ in range(100)],
"y": [random.randint(0,100) for _ in range(100)],
"z": [random.randint(0,100) for _ in range(100)],
})
ddf = dd.from_pandas(df, npartitions=10)
unique = {
name: ddf[name].nunique()
for name in ddf.columns
}
# traverse=True is default, but being explicit that we are traversing the dict for dask objects
dask.compute(unique, traverse=True)
@Mohamed 从 Dask 版本2022.01.0
, dask.DataFrame.nunique()
已经实现:
import random
import pandas
import dask.dataframe as dd
df = pandas.DataFrame({
"x": [random.randint(0,100) for _ in range(100)],
"y": [random.randint(0,100) for _ in range(100)],
"z": [random.randint(0,100) for _ in range(100)],
})
ddf = dd.from_pandas(df, npartitions=10)
ddf.nunique().compute()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.