Найдите половину каждой группы с помощью Pandas GroupBy

Мне нужно выбрать половину кадра данных, используя 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 соответственно. Что мне нужно, так это взять только ПЕРВУЮ половину (или пол (N/2)) каждой группы.

Из моего (очень ограниченного) опыта работы с пандами groupbyдолжно быть что-то вроде:

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

где k_i это половина размера каждой группы. Есть ли простое решение, чтобы найти k_i?

2 ответа

Решение

IIUC, вы можете использовать индексную нарезку с размером //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

Вы можете сгруппировать по 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
Другие вопросы по тегам