我有以下数据:

    group   cluster probabilityA    probabilityB
0   a   0   0.28    0.153013
1   a   0   0.28    0.133686
2   a   0   0.28    0.058366
3   a   0   0.28    0.091937
4   a   1   0.50    0.040095
5   a   1   0.50    0.150359
6   a   2   0.32    0.043512
7   a   2   0.32    0.088408
8   a   2   0.32    0.005158
9   a   2   0.32    0.107054
10  a   2   0.32    0.029050
11  a   2   0.32    0.099361
12  b   0   0.40    0.057752
13  b   0   0.40    0.177103
14  b   1   0.60    0.218634
15  b   1   0.60    0.098535
16  b   1   0.60    0.065746
17  b   1   0.60    0.190805
18  b   1   0.60    0.191425


我想做的是,根据probabilityB并根据每个cluster的大小份额,选择每个组的前5行(任意数,可以为N)。如果仅查看组a,则有3个簇:0、1和2。它们各自的大小份额为:

group  cluster
a      0          0.333333
       1          0.166667
       2          0.500000
Name: probabilityA, dtype: float64


在这里,如果我想要基于此份额的前5行,我会选择

(round
      (df
            .groupby(["group", "cluster"])["probabilityA"]
            .count() /
       df
            .groupby(["group", "cluster"])["probabilityA"]
            .count()
            .sum(level = 0)
       * 5)

group  cluster
a      0          2.0
       1          1.0
       2          2.0


基于probabilityB列,群集0和2中有2个元素,群集1中只有1个元素。
因此,我的结果将如下所示(在下面的示例中索引是不相关的):

    group   cluster probabilityA    probabilityB
0   a   1   0.50    0.150359
1   a   2   0.32    0.107054
2   a   2   0.32    0.088408
3   a   0   0.28    0.153013
4   a   0   0.28    0.133686
5   b   0   0.40    0.177103
6   b   1   0.60    0.218634
7   b   1   0.60    0.191425
8   b   1   0.60    0.190805
9   b   1   0.60    0.098535


有办法可以实现吗?

提前致谢!

最佳答案

我认为,最明确的解决方案是将tke任务划分为多个步骤:


为每个顶级组生成计数:

c1 = df.groupby(["group"])["probabilityA"].count().rename('c1')


对于您的数据,结果是:

group
a    12
b     7
Name: c1, dtype: int64

设置从每个顶级组获取的行数:

N = 5

生成要从每个第二级组获取的行数:

cnt = df.groupby(["group", "cluster"])["probabilityA"].count().rename('c2')\
    .reset_index(level=1).join(c1).set_index('cluster', append=True)\
    .apply(lambda row: N * row.c2 / row.c1, axis=1).round().astype(int)


对于您的数据,结果是:

group  cluster
a      0          2
       1          1
       2          2
b      0          1
       1          4
dtype: int32

然后定义函数,重新列出“顶部”行的相应数目:

def takeFirst(grp):
    grpKey = tuple(grp.iloc[0, 0:2])
    grpCnt = cnt.loc[grpKey]
    return grp.nlargest(grpCnt, 'probabilityB')

最后一步是计算结果:

df.groupby(['group', 'cluster']).apply(takeFirst)


对于您的数据,结果是:

                 group  cluster  probabilityA  probabilityB
group cluster
a     0       0      a        0          0.28      0.153013
              1      a        0          0.28      0.133686
      1       5      a        1          0.50      0.150359
      2       9      a        2          0.32      0.107054
              11     a        2          0.32      0.099361
b     0       13     b        0          0.40      0.177103
      1       14     b        1          0.60      0.218634
              18     b        1          0.60      0.191425
              17     b        1          0.60      0.190805
              15     b        1          0.60      0.098535



为了方便起见,我毫不犹豫地将组和群集作为索引列
确定他们来自哪个小组的身份,但是在最后
您可以附加.reset_index(level=[0,1], drop=True)来删除的版本
他们。

关于python - Pandas groupby根据列值和组大小份额选择前N行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60127601/

10-12 13:31