我有以下数据:
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/