簡體   English   中英

Dask-Dataframe 列中唯一值的數量

[英]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.0dask.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM