簡體   English   中英

Python - 熊貓 - 找到最頻繁的組合與領帶分辨率 - 性能

[英]Python - pandas - find most frequent combination with tie-resolution - performance

數據
我有一個看起來像這樣的數據集:

| id    | string_col_A | string_col_B | creation_date |
|-------|--------------|--------------|---------------|
| x12ga | STR_X1       | STR_Y1       | 2020-11-01    |
| x12ga | STR_X1       | STR_Y1       | 2020-10-10    |
| x12ga | STR_X2       | STR_Y2       | 2020-11-06    |
| x21ab | STR_X4       | STR_Y4       | 2020-11-06    |
| x21ab | STR_X5       | STR_Y5       | 2020-11-02    |
| x11aa | STR_X3       | STR_Y3       | None          |  

目標

  1. 我想為每個 id 找到最頻繁的值組合。
  2. 此外,在平局的情況下,我想提取最新的組合。

即上表的結果是:

| id    | string_col_A | string_col_B |
|-------|--------------|--------------|
| x12ga | STR_X1       | STR_Y1       |
| x21ab | STR_X4       | STR_Y4       |
| x11aa | STR_X3       | STR_Y3       |

解釋

  1. 對於x12ga ,解釋很簡單。 STR_X1, STR_Y1 出現兩次,STR_X2, STR_Y2 只出現一次(即沒有平局決議)
  2. x11aa很簡單,只有一行
  3. 對於x21ab ,兩個組合都有 1 行,但 STR_X4, STR_Y4 是最新的。

代碼
這是我到目前為止所擁有的:


def reducer(id_group):
    id_with_sizes = id_group.groupby(
            ["id", "string_col_A", "string_col_B"], dropna=False).agg({
            'creation_date': [len, max]
            }).reset_index()
    id_with_sizes.columns = [
            "id", "string_col_A", "string_col_B", "row_count",
            "recent_date"
            ]
    id_with_sizes.sort_values(by=["row_count", "recent_date"],
                           ascending=[False, False],
                           inplace=True)
    return id_with_sizes.head(1).drop(["recent_date", "row_count"], axis=1)

我像這樣調用上述方法:

assignment =  all_data.groupby("id").apply(inventor_reduce)

問題
上面的代碼在測試數據時工作正常,但我正在使用的實際數據集有超過 1000 萬行,大約有 300 萬個 ID。 因此,處理 10K IDS 需要 5 分鍾,總共需要 25 小時來處理。 我想提高性能。

解決方案
我在 stackoverflow(和其他地方)上看到了關於獲得頻繁組合(盡管沒有領帶解決方案)和關於對過程進行矢量化以提高性能的問題。 我不太確定如何解決我上面的問題。

理想情況下,解決方案仍然是基於熊貓的(使用熊貓代碼看起來和閱讀起來更好)

  1. 您可以創建一系列的s ,結合兩列
  2. 返回最大計數的索引
  3. 按該索引過濾。 注意:如果您使用的是早期版本的.groupby代碼中取出, sort=False並在最后進行排序。

——

s = df['string_col_A'] + df['string_col_B']
df['max'] = df.groupby(['id',s])['id'].transform('count')
df = df.iloc[df.groupby('id', sort=False)['max'].idxmax().values].drop(['max', 'creation_date'], axis=1)
df
Out[1]: 
      id string_col_A string_col_B
0  x12ga       STR_X1       STR_Y1
3  x21ab       STR_X4       STR_Y4
5  x11aa       STR_X3       STR_Y3

您只需要按id列進行分組,並基於此找到最常用的數據(模式)。

為了使事情更容易,您可以創建另一列combined_str

df['combined_str'] = df['string_col_A'] + df['string_col_B']

id分組並使用pd.Series.mode函數減少:

df = df.sort_values(by=['creation_date'])
df = df.groupby(['id'])['combined_str'].agg(most_common = ('combined_str', pd.Series.mode))

讓我們嘗試groupbytransform ,然后獲取最常見值的計數,然后sort_valuesdrop_duplicates

df['help'] = df.groupby(['id','string_col_A','string_col_B'])['string_col_A'].transform('count')
out = df.sort_values(['help','creation_date'],na_position='first').drop_duplicates('id',keep='last').drop(['help','creation_date'],1)
out
Out[122]: 
      id string_col_A string_col_B
3  x21ab       STR_X4       STR_Y4
5  x11aa       STR_X3       STR_Y3
0  x12ga       STR_X1       STR_Y1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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