Количество уникальных значений частоты Pandas

#python #pandas #time-series #frequency

#python #pandas #временные ряды #частота

Вопрос:

У меня есть серия Pandas следующим образом :

 2014-05-24 23:59:49     1.3
2014-05-24 23:59:50    2.17
2014-05-24 23:59:50    1.28
2014-05-24 23:59:51    1.30
2014-05-24 23:59:51    2.17
2014-05-24 23:59:53    2.17
2014-05-24 23:59:58    2.17
Name: api_id, Length: 483677
  

Я пытаюсь подсчитать для каждого идентификатора частоту в день.
На данный момент я делаю это :

 count = {}
for x in apis.unique():
    count[x] = apis[apis == x].resample('D','count')
count_df = pd.DataFrame(count)
  

Это дает мне то, что я хочу, а именно :

             ...    2.13   2.17   2.4  2.6  2.7  3.5(user)  3.9  4.2   5.1  5.6  
timestamp   ...                                                                 
2014-05-22  ...     391  49962  3727  161    2        444  113   90  1398   90  
2014-05-23  ...     450  49918  3861  187    1        450  170   90   629   90  
2014-05-24  ...     396  46359  3603  172    3        513  171   89   622   90  
  

Но есть ли способ сделать это без цикла for ?

Ответ №1:

Вы можете использовать value_counts функцию для этого (docs), применив это после groupby (что аналогично resample('D') тому, что вы сделали, но повторная выборка ожидает агрегированный результат, поэтому в этом случае мы должны использовать более общий groupby). С небольшим примером:

 In [16]: s = pd.Series([1,1,2,2,1,2,5,6,2,5,4,1], index=pd.date_range('2012-01-01', periods=12, freq='8H'))

In [17]: counts = s.groupby(pd.Grouper(freq='D')).value_counts()

In [18]: counts
Out[18]: 
2012-01-01  1    2
            2    1
2012-01-02  2    2
            1    1
2012-01-03  2    1
            6    1
            5    1
2012-01-04  1    1
            5    1
            4    1
dtype: int64
  

Чтобы получить это в желаемом формате, вы можете просто распаковать это (переместить индексы строк второго уровня в столбцы):

 In [19]: counts.unstack()
Out[19]: 
             1   2   4   5   6
2012-01-01   2   1 NaN NaN NaN
2012-01-02   1   2 NaN NaN NaN
2012-01-03 NaN   1 NaN   1   1
2012-01-04   1 NaN   1   1 NaN
  

Примечание: для использования groupby(pd.Grouper(freq='D')) вам нужен pandas 0.14. Если у вас есть более старая версия, вы можете использовать groupby(pd.TimeGrouper(freq='D')) для получения точно такой же. Это также похоже на выполнение groupby(s.index.date) (с той разницей, что у вас есть datetime.date объекты в индексе).

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

1. Большое спасибо, именно то, что я хотел!