Pandy: resample timeseries with groupby

Biorąc pod uwagę poniższy ramka danych pandy:

In [115]: times = pd.to_datetime(pd.Series(['2014-08-25 21:00:00','2014-08-25 21:04:00',
                                            '2014-08-25 22:07:00','2014-08-25 22:09:00']))
          locations = ['HK', 'LDN', 'LDN', 'LDN']
          event = ['foo', 'bar', 'baz', 'qux']
          df = pd.DataFrame({'Location': locations,
                             'Event': event}, index=times)
          df
Out[115]:
                               Event Location
          2014-08-25 21:00:00  foo   HK
          2014-08-25 21:04:00  bar   LDN
          2014-08-25 22:07:00  baz   LDN
          2014-08-25 22:09:00  qux   LDN

Chciałbym ponownie pobrać dane, aby agregować je co godzinę według liczby, podczas grupowania według lokalizacji, aby stworzyć ramkę danych, która wygląda tak:

Out[115]:
                               HK    LDN
          2014-08-25 21:00:00  1     1
          2014-08-25 22:00:00  0     2
Próbowałem różnych kombinacji resample() i groupby (), ale bez powodzenia. Jak mam to zrobić?
Author: AshB, 2015-08-14

3 answers

W moim oryginalnym poście zasugerowałem użycie pd.TimeGrouper. Obecnie używa się pd.Grouper zamiast pd.TimeGrouper. Składnia jest w dużej mierze taka sama, ale TimeGrouper jest obecnie przestarzałe na rzecz pd.Grouper.

Ponadto, podczas gdy pd.TimeGrouper może grupować tylko według DatetimeIndex, pd.Grouper może grupować według DateTime kolumny , które można określić poprzez key parametr .


Przydałby się pd.Grouper do grupy DatetimeIndex'ed DataFrame według godziny:

grouper = df.groupby([pd.Grouper('1H'), 'Location'])

Użycie count aby policzyć liczbę zdarzeń w każdej grupie:

grouper['Event'].count()
#                      Location
# 2014-08-25 21:00:00  HK          1
#                      LDN         1
# 2014-08-25 22:00:00  LDN         2
# Name: Event, dtype: int64

Użycie unstack aby przenieść poziom indeksu Location na poziom kolumny:

grouper['Event'].count().unstack()
# Out[49]: 
# Location             HK  LDN
# 2014-08-25 21:00:00   1    1
# 2014-08-25 22:00:00 NaN    2

A następnie użyj fillna, aby zmienić Nan na zera.


Składając wszystko razem,

grouper = df.groupby([pd.Grouper('1H'), 'Location'])
result = grouper['Event'].count().unstack('Location').fillna(0)

Location             HK  LDN
2014-08-25 21:00:00   1    1
2014-08-25 22:00:00   0    2
 26
Author: unutbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 21:42:36

Pandy 0.21 odpowiedź: TimeGrouper jest coraz przestarzały

Istnieją dwie opcje, aby to zrobić. W rzeczywistości mogą dawać różne wyniki w oparciu o Twoje dane. Pierwsza opcja grupuje według lokalizacji, a w obrębie lokalizacji grupy według godziny. Druga opcja grupuje jednocześnie według lokalizacji i godziny.

Opcja 1 : Użyj groupby + resample

grouped = df.groupby('Location').resample('H')['Event'].count()

Opcja 2 : Grupuj zarówno lokalizację, jak i dane razem z groupby(pd.Grouper)

grouped = df.groupby(['Location', pd.Grouper(freq='H')])['Event'].count()

Oboje wynik będzie następujący:

Location                     
HK        2014-08-25 21:00:00    1
LDN       2014-08-25 21:00:00    1
          2014-08-25 22:00:00    2
Name: Event, dtype: int64

A następnie przekształcić:

grouped.unstack('Location', fill_value=0)

Wyświetli

Location             HK  LDN
2014-08-25 21:00:00   1    1
2014-08-25 22:00:00   0    2
 22
Author: Ted Petrou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 22:38:01

Multiple Column Group By

Untubu jest na miejscu z jego odpowiedzi, ale chciałem dodać, co można zrobić, jeśli masz trzecią kolumnę, powiedzieć Cost i chciał agregować to jak powyżej. To właśnie dzięki połączeniu odpowiedzi unutbu i tej dowiedziałem się, jak to zrobić i pomyślałem, że podzielę się z przyszłymi użytkownikami.

Utwórz ramkę danych za pomocą Cost colunm.

In[1]: 
      import pandas as pd

      times = pd.to_datetime(pd.Series(['2014-08-25 21:00:00',
                  '2014-08-25 21:04:00','2014-08-25 22:07:00','2014-08-25 22:09:00']))

      locations = ['HK', 'LDN', 'LDN', 'LDN']
      event = ['foo', 'bar', 'baz', 'qux']
      cost = [20, 24, 34, 52] # add in cost colunm

      df = pd.DataFrame({'Location': locations, 'Event': event, 'Cost': cost}, index=times)
      df

Out[1]:
                               Event Location Cost
          2014-08-25 21:00:00  foo   HK       20
          2014-08-25 21:04:00  bar   LDN      24
          2014-08-25 22:07:00  baz   LDN      34
          2014-08-25 22:09:00  qux   LDN      52

Teraz grupujemy za pomocą funkcji agg, aby określić agregację każdej kolumny metoda, tj. count, mean, sum itp.

In[2]:    
      df = df.groupby([pd.TimeGrouper('1H'), 'Location']).agg({'Event': np.sum,
                                                               'Cost': np.mean})

Out[2]:
                               Location    Event     Cost
          2014-08-25 21:00:00  HK          1         20
                               LDN         1         24
          2014-08-25 22:00:00  LDN         2         43

Następnie finał unstack z wypełnieniem NaN z zerami i wyświetlaniem jako int, ponieważ jest ładny.

In[3]: 
      df.df.unstack().fillna(0).astype(int)

Out[3]:

                                Cost      Event
                    Location    HK  LDN   HK   LDN
         2014-08-25 21:00:00    20  24    1    1
         2014-08-25 22:00:00    0   43    0    2
 6
Author: josh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:14