Python:根据多个分组对唯一变量进行分组计数,无需重复计数。

3

我有一个包含三列的数据框(Dataframe):

ID  Round  Investor
X   1      A
X   2      A
X   2      B
X   3      A
Y   1      A
Y   1      B
Y   1      C
Y   2      B
Y   2      D

我想要统计每个ID在每个轮次中的唯一投资者数量。但我不希望它重复计算上一轮已经出现的投资者。我正在使用以下代码:

print(df.groupby(['ID', 'Round'])['Investor'].nunique())

这将导致以下结果:

ID  Round  Unique Investor
X   1      1
    2      2
    2      2
    3      1
Y   1      3
    1      3
    1      3
    2      2
    2      2

但我不希望这次投资在同一ID的早期轮次中已经计算过了。
ID  Round  Unique Investor
X   1      1
    2      1
    2      1
    3      0
Y   1      3
    1      3
    1      3
    2      1
    2      1

非常感谢您的帮助!

2个回答

2
您可以定义一个辅助列Investor2,该列在ID下进行分组,并使用Series.drop_duplicates删除相同ID中的重复项。

然后,像之前一样,在这个Investor2列上使用.transform()nuniqueIDRound进行分组,如下所示:
df['Unique Investor'] = (
    df.assign(Investor2=df.groupby('ID')['Investor'].apply(pd.Series.drop_duplicates).droplevel(0))
      .groupby(['ID', 'Round'])['Investor2'].transform('nunique')
    )

结果:

print(df)

  ID  Round Investor  Unique Investor
0  X      1        A                1
1  X      2        A                1
2  X      2        B                1
3  X      3        A                0
4  Y      1        A                3
5  Y      1        B                3
6  Y      1        C                3
7  Y      2        B                1
8  Y      2        D                1

谢谢,老兄!这就解决了问题。你不会顺便知道获取累积独立投资者数量的快捷方式吧?那么我们可以得到:Acc_unique_investor = [1, 2, 2, 2, 3, 3, 3, 3, 4]。 - Hassan33
@Hassan33 这是一个有趣的新问题。我认为困难在于同一轮比赛中存在多个条目,而我们需要为重复值每轮仅计算一次。 - SeaBean
@Hassan33 对于你的新问题,实际上它与这里的问题非常相似。请尝试以下代码:(df.assign(unique_investor2=df.groupby(['ID', 'Round'])['Unique Investor'].apply(pd.Series.drop_duplicates).droplevel([0,1])) .groupby('ID')['unique_investor2'].cumsum().ffill(downcast='infer') ) - SeaBean
1
非常感谢,我做了另一种解决方案,但你的方法更简单、更快。 - Hassan33

0
一个可能的解决方案是基于'ID'和投资者,丢弃重复数据,按ID分组并四舍五入以获取独特数量,然后将结果合并回主数据框。
dups = ['ID', 'Investor']

group = ['ID', 'Round']

mapping = (df.drop_duplicates(subset = dups)
             .groupby(group)
             .Investor
             .nunique()
          )

(df.filter(group)
   .merge(mapping, left_on = group, 
          right_index = True, how = 'left')
   .fillna(0, downcast='infer')
)

  ID  Round  Investor
0  X      1         1
1  X      2         1
2  X      2         1
3  X      3         0
4  Y      1         3
5  Y      1         3
6  Y      1         3
7  Y      2         1
8  Y      2         1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接