使用 Pandas GroupBy 找到每个组的一半

Find half of each group with Pandas GroupBy

我需要 select 使用 groupby 的数据帧的一半,其中每个组的大小未知,并且可能因组而异。例如:

       index  summary  participant_id
0     130599     17.0              13
1     130601     18.0              13
2     130603     16.0              13
3     130605     15.0              13
4     130607     15.0              13
5     130609     16.0              13
6     130611     17.0              13
7     130613     15.0              13
8     130615     17.0              13
9     130617     17.0              13
10     86789     12.0              14
11     86791      8.0              14
12     86793     21.0              14
13     86795     19.0              14
14     86797     20.0              14
15     86799      9.0              14
16     86801     10.0              14
20    107370      1.0              15
21    107372      2.0              15
22    107374      2.0              15
23    107376      4.0              15
24    107378      4.0              15
25    107380      7.0              15
26    107382      6.0              15
27    107597      NaN              15
28    107384     14.0              15

groupyby('participant_id') 组的大小分别为 10、7、9,participant_id 13、14、15。我需要的是只占每组的前半部分(或 floor(N/2))。

根据我对 Pandas groupby 的(非常有限的)经验,它应该是这样的:

df.groupby('participant_id')[['summary','participant_id']].apply(lambda x: x[:k_i])

其中 k_i 是每组人数的一半。有没有简单的解决方案来找到 k_i?

可以按participant_id分组,用transform方法检查其索引是否在前半部分。这将创建一个布尔系列。然后使用这个布尔系列来过滤掉你的原始数据框。

criteria = df.groupby('participant_id')['participant_id']\
             .transform(lambda x:  np.arange(len(x)) < int(len(x) / 2))
df[criteria]

     index  summary  participant_id
0   130599     17.0              13
1   130601     18.0              13
2   130603     16.0              13
3   130605     15.0              13
4   130607     15.0              13
10   86789     12.0              14
11   86791      8.0              14
12   86793     21.0              14
20  107370      1.0              15
21  107372      2.0              15
22  107374      2.0              15
23  107376      4.0              15

IIUC,您可以在 lambda 中使用大小为 //2 的索引切片:

df.groupby('participant_id').apply(lambda x: x.iloc[:x.participant_id.size//2])

输出:

                    index  summary  participant_id
participant_id                                    
13             0   130599     17.0              13
               1   130601     18.0              13
               2   130603     16.0              13
               3   130605     15.0              13
               4   130607     15.0              13
14             10   86789     12.0              14
               11   86791      8.0              14
               12   86793     21.0              14
15             20  107370      1.0              15
               21  107372      2.0              15
               22  107374      2.0              15
               23  107376      4.0              15