Случайным образом отбрасывайте строки из фрейма данных, чтобы не существовало строк с числом более N

#python #pandas #dataframe

Вопрос:

Учитывая df фрейм данных с закодированными темами и элементами, который выглядит как

 topic    item
0        bucket
1        fish
2        car
0        pail
2        truck
3        glove 
 

где есть X темы и Y элементы, например, если я посмотрю количество элементов в каждой теме

 print(df.groupby(by='topic').agg('count'))

                 item
topic                
0                8568   
1                7539  
2               48700   
3               26036   
4                4190  
5                2153 
...               ...
X-2               328
X-1              5942
X               15871
 

Как я мог бы сделать так, чтобы ни в одной теме не было более N связанных элементов? Например, допустим N = 5000 . Затем, если бы я сделал подсчет, я бы получил

 print(df.groupby(by='topic').agg('count'))

                 item
topic                
0                5000   
1                5000  
2                5000   
3                5000   
4                4190  
5                2153 
...               ...
X-2               328
X-1              5000
X                5000
 

Где все, что имеет значение выше 5000, уменьшается до 5000, а все, что ниже, остается нетронутым. Отброшенные строки также должны быть отброшены случайным образом, а не только первыми появившимися.

 psuedocode:

# Randomly drops rows by topic until there are no topics that have a count
# above 5000
df.drop_rows_by_count(
                      based_on='topic'
                      above_below='above', 
                      count=5000,
                      how='random'
)
 

Как бы я это сделал?

Комментарии:

1. Вы хотите удалить строки из исходного фрейма данных, чтобы в каждой теме было не более n экземпляров?

2. Это именно то, что я хочу сделать @HenryEcker

Ответ №1:

Сначала перетасуйте весь кадр данных с sample аргументом и frac аргументом 1 (который в основном «пробует» весь кадр данных). Этот replace=False аргумент не позволяет пандам дважды выбирать одну и ту же строку в процессе выборки.

Затем используйте head , чтобы получить первые N случаев (в случайном порядке, так как мы просто перетасовали строки):

 df.sample(frac=1, replace=False).groupby('topic').head(5000)