2016-12-26 2 views
5

Я следующие dataframe:Панды - агрегат, сортировать и nlargest внутри GroupBy

     some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011 

И мне нужно сделать что-то подобное преобразование («размер») со следующими сортировать и получить значения N макс. Чтобы получить что-то вроде этого (N = 2):

   some_id size 
2016-12-26  001  3 
       008  1 
2016-12-27  009  2 
       003  1 

Есть элегантный способ сделать это в панд 0.19.x?

ответ

4

Используйте value_counts, чтобы вычислить различные количества после группировки на date часть вашего DateTimeIndex. По умолчанию они сортируют их по убыванию.

Вам нужно всего лишь взять верхние 2 строки этого результата, чтобы получить самую большую (верхнюю часть).

fnc = lambda x: x.value_counts().head(2) 
grp = df.groupby(df.index.date)['some_id'].apply(fnc).reset_index(1, name='size') 
grp.rename(columns={'level_1':'some_id'}) 

enter image description here

+0

Это была моя первая идея, но я не могу применять 'head' или' nlargest' после value_counts. –

+0

* См. Отредактированный пост * –

+1

Выглядит хорошо. Я думаю, мы не можем сбросить индекс. Просто 'df.groupby (df.index.date) ['some_id']. Apply (lambda x: x.value_counts(). Head (2))' –

0

Если у вас уже есть sizes столбец, вы можете использовать следующее.

df.groupby('some_id')['size'].value_counts().groupby(level=0).nlargest(2) 

В противном случае вы можете использовать этот подход.

import pandas as pd 

df = pd.DataFrame({'some_id':[1,1,1,8,9,9,3,11], 
        'some_idx':[26,26,26,26,27,27,27,27]}) 

sizes = df.groupby(['some_id', 'some_idx']).size() 

sizes.groupby(level='some_idx').nlargest(2) 

# some_idx some_id some_idx 
# 26  1  26   3 
#   8  26   1 
# 27  9  27   2 
#   3  27   1 
+0

Я думаю, что это очень близко, но у меня нет размера столбца и его нужно вычислить. –

+0

А, вы. Отредактировано с учетом этого требования. Я думаю, что создание нового объекта 'groupby' является самым ясным для понимания. – 3novak

2

установка

from io import StringIO 
import pandas as pd 

txt = """     some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011""" 

df = pd.read_csv(StringIO(txt), sep='\s{2,}', engine='python') 

df.index = pd.to_datetime(df.index) 
df.some_id = df.some_id.astype(str).str.zfill(3) 

df 

        some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011 

использованием nlargest

df.groupby(pd.TimeGrouper('D')).some_id.value_counts() \ 
    .groupby(level=0, group_keys=False).nlargest(2) 

      some_id 
2016-12-26 001  3 
      008  1 
2016-12-27 009  2 
      003  1 
Name: some_id, dtype: int64 
2

Вы должны быть в состоянии сделать это в одной строке.

df.resample('D')['some_id'].apply(lambda s: s.value_counts().iloc[:2]) 
Смежные вопросы