Вот еще один вариант, который основывается на некоторых ответах в посте, который вы упомянули.
Прежде всего, здесь есть быстрая функция для округления в большую или меньшую сторону.Если мы хотим, чтобы верхние 30% строк в кадре данных имели длину 8 строк, мы бы попытались взять 2,4 строки.Таким образом, нам нужно будет либо округлить вверх или вниз.
Мой предпочтительный вариант - округлить.Это потому, что, например, если бы мы взяли 50% строк, но имели одну группу, в которой был только один ряд, мы все равно сохранили бы эту одну строку.Я держал это отдельно, так что вы можете изменить округление по своему усмотрению
def round_func(x, up=True):
'''Function to round up or round down a float'''
if up:
return int(x+1)
else:
return int(x)
Далее я создаю фрейм данных для работы и устанавливаю параметр p
, чтобы быть частью строк из каждой группы, которую мыдолжны держать.Все следует, и я прокомментировал это, так что, надеюсь, вы можете следовать.
import pandas as pd
df = pd.DataFrame({'id':[1,1,1,2,2,2,2,3,4],'value':[1,2,3,1,2,3,4,1,1]})
p = 0.30 # top fraction to keep. Currently set to 80%
df_top = df.groupby('id').apply( # group by the ids
lambda x: x.reset_index()['value'].nlargest( # in each group take the top rows by column 'value'
round_func(x.count().max()*p))) # calculate how many to keep from each group
df_top = df_top.reset_index().drop('level_1', axis=1) # make the dataframe nice again
df выглядел так
id value
0 1 1
1 1 2
2 1 3
3 2 1
4 2 2
5 2 3
6 2 4
7 3 1
8 4 1
df_top выглядит так
id value
0 1 3
1 2 4
2 2 3
3 3 1
4 4 1