簡體   English   中英

根據多列聚合函數的條件結果計算唯一記錄

[英]Count unique records based on conditional result of aggregate functions on multiple columns

我的數據如下所示:

df = pd.DataFrame({'ID': [1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4,
                          4, 4, 5, 5, 5],
                   'group': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B',
                             'B', 'B', 'B', 'B', 'B', 'B'],
                   'attempts': [0, 1, 1, 1, 1, 1, 1, 0, 1,
                                1, 1, 1, 0, 0, 1, 0],
                   'successes': [1, 0, 0, 0, 0, 0, 0, 1, 0,
                                 0, 0, 0, 1, 1, 0, 1],
                   'score': [None, 5, 5, 4, 5, 4, 5, None, 1, 5,
                             0, 1, None, None, 1, None]})

## df output
   ID group attempts successes score
0   1     A        0         1  None
1   1     A        1         0     5
2   1     A        1         0     5
3   1     A        1         0     4
4   2     A        1         0     5
5   2     A        1         0     4
6   3     A        1         0     5
7   3     A        0         1  None
8   3     A        1         0     1
9   4     B        1         0     5
10  4     B        1         0     0
11  4     B        1         0     1
12  4     B        0         1  None
13  5     B        0         1  None
14  5     B        1         0     1
15  5     B        0         1  None

我試圖按兩列( groupscore )分組,並在首先確定( groupID )的哪些組在所有score值中至少有 1 個successes計數之后計算唯一ID的數量。 換句話說,如果 ID 至少有一個關聯成功,我只想在聚合中計算一次(唯一)ID。 我也只想計算每個 ( group , ID ) 對的唯一 ID,而不attempt_counts包含的嘗試計數的數量(即,如果有 5 個成功計數的總和,我只想包括 1 個)。

successesattempts列是二進制的(只有 1 或 0)。 例如,對於 ID = 1、group = A,至少有 1 次成功。 因此,在計算每個( groupscore )的唯一 ID 數時,我將包括該ID

我希望最終的 output看起來像這樣,這樣我就可以計算每個( groupscore )組合的獨特成功與獨特嘗試的比率。

group score successes_count attempts_counts ratio
    A     5              2                3  0.67
          4              1                2  0.50
          1              1                1   1.0              
          0              0                0   inf
    B     5              1                1   1.0
          4              0                0   inf
          1              2                2   1.0
          0              1                1   1.0

到目前為止,我已經能夠運行 pivot 表來計算每個( groupID )的總和,以識別那些至少有 1 次成功的 ID。 但是,我不確定使用它來達到我想要的最終 state 的最佳方法。

p = pd.pivot_table(data=df_new,
                values=['ID'],
                index=['group', 'ID'],
                columns=['successes', 'attempts'],
                aggfunc={'ID': 'count'})
# p output
            ID     
successes    0    1
attempts     1    0
group ID           
A     1    3.0  1.0
      2    2.0  NaN
      3    2.0  1.0
B     4    3.0  1.0
      5    1.0  2.0

讓我們嘗試一下:

import numpy as np
import pandas as pd

df = pd.DataFrame({'ID': [1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4,
                          4, 4, 5, 5, 5],
                   'group': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B',
                             'B', 'B', 'B', 'B', 'B', 'B'],
                   'attempts': [0, 1, 1, 1, 1, 1, 1, 0, 1,
                                1, 1, 1, 0, 0, 1, 0],
                   'successes': [1, 0, 0, 0, 0, 0, 0, 1, 0,
                                 0, 0, 0, 1, 1, 0, 1],
                   'score': [None, 5, 5, 4, 5, 4, 5, None, 1, 5,
                             0, 1, None, None, 1, None]})

# Groups With At least 1 Success
m = df.groupby('group')['successes'].transform('max').astype(bool)
# Filter Out
df = df[m]

# Replace 0 successes with NaNs
df['successes'] = df['successes'].replace(0, np.nan)
# FFill BFill each group so that any success will fill the group
df['successes'] = df.groupby(['ID', 'group'])['successes'] \
    .apply(lambda s: s.ffill().bfill())

# Pivot then stack to make sure each group has all score values
# Sort and reset index
# Rename Columns
# fix types
p = df.drop_duplicates() \
    .pivot_table(index='group',
                 columns='score',
                 values=['attempts', 'successes'],
                 aggfunc='sum',
                 fill_value=0) \
    .stack() \
    .sort_values(['group', 'score'], ascending=[True, False]) \
    .reset_index() \
    .rename(columns={'attempts': 'attempts_counts',
                     'successes': 'successes_count'}) \
    .convert_dtypes()

# Calculate Ratio
p['ratio'] = p['successes_count'] / p['attempts_counts']
print(p)

Output:

  group  score  attempts_counts  successes_count     ratio
0     A      5                3                2  0.666667
1     A      4                2                1       0.5
2     A      1                1                1       1.0
3     A      0                0                0       NaN
4     B      5                1                1       1.0
5     B      4                0                0       NaN
6     B      1                2                2       1.0
7     B      0                1                1       1.0

暫無
暫無

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

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