Étant donné le pandas DataFrame:
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
Je voudrais rééchantillonner les données pour les agréger toutes les heures en nombre tout en les regroupant par emplacement pour produire un bloc de données qui ressemble à ceci:
Out[115]:
HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
J'ai essayé différentes combinaisons de resample () et groupby () mais sans succès. Comment pourrais-je m'y prendre?
Dans mon message d'origine, j'ai suggéré d'utiliser pd.TimeGrouper
. De nos jours, utilisez pd.Grouper
au lieu de pd.TimeGrouper
. La syntaxe est largement la même, mais TimeGrouper
est désormais obsolète en faveur de pd.Grouper
.
De plus, tandis que pd.TimeGrouper
n'a pu être regroupé que par DatetimeIndex, pd.Grouper
peut regrouper par colonnes datetime que vous pouvez spécifier via le paramètre key
.
Vous pouvez utiliser un pd.Grouper
pour regrouper le DataFrame DatetimeIndex'ed par heure:
grouper = df.groupby([pd.Grouper(freq='1H'), 'Location'])
utilisez count
pour compter le nombre d'événements dans chaque groupe:
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
utilisez unstack
pour déplacer le niveau d'index Location
vers un niveau de colonne:
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
puis utilisez fillna
pour changer les NaN en zéros.
Mettre tous ensemble,
grouper = df.groupby([pd.Grouper(freq='1H'), 'Location'])
result = grouper['Event'].count().unstack('Location').fillna(0)
les rendements
Location HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
Il existe deux options pour ce faire. Ils peuvent en fait donner des résultats différents en fonction de vos données. La première option regroupe par emplacement et dans les groupes d'emplacement par heure. La deuxième option regroupe en même temps l'emplacement et l'heure.
Option 1 : utilisez groupby + resample
grouped = df.groupby('Location').resample('H')['Event'].count()
Option 2 : regroupez à la fois l'emplacement et DatetimeIndex avec groupby(pd.Grouper)
grouped = df.groupby(['Location', pd.Grouper(freq='H')])['Event'].count()
Les deux entraîneront les résultats suivants:
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
Et puis remodeler:
grouped.unstack('Location', fill_value=0)
Sortira
Location HK LDN
2014-08-25 21:00:00 1 1
2014-08-25 22:00:00 0 2
untubu est sur place avec sa réponse, mais je voulais ajouter ce que vous pourriez faire si vous aviez une troisième colonne, dites Cost
et vouliez l'agréger comme ci-dessus. C'est en combinant la réponse d'unutbu et celle-ci que j'ai découvert comment faire et pensé que je partagerais pour les futurs utilisateurs.
Créez un DataFrame avec la colonne Cost
:
In[1]:
import pandas as pd
import numpy as np
times = pd.to_datetime([
"2014-08-25 21:00:00", "2014-08-25 21:04:00",
"2014-08-25 22:07:00", "2014-08-25 22:09:00"
])
df = pd.DataFrame({
"Location": ["HK", "LDN", "LDN", "LDN"],
"Event": ["foo", "bar", "baz", "qux"],
"Cost": [20, 24, 34, 52]
}, index = times)
df
Out[1]:
Location Event Cost
2014-08-25 21:00:00 HK foo 20
2014-08-25 21:04:00 LDN bar 24
2014-08-25 22:07:00 LDN baz 34
2014-08-25 22:09:00 LDN qux 52
Maintenant, nous regroupons en utilisant la fonction agg
pour spécifier la méthode d'agrégation de chaque colonne, par exemple compte, moyenne, somme, etc.
In[2]:
grp = df.groupby([pd.Grouper(freq = "1H"), "Location"]) \
.agg({"Event": np.size, "Cost": np.mean})
grp
Out[2]:
Event Cost
Location
2014-08-25 21:00:00 HK 1 20
LDN 1 24
2014-08-25 22:00:00 LDN 2 43
Puis le unstack
final avec fill NaN
avec des zéros et s'affiche comme int
parce que c'est sympa.
In[3]:
grp.unstack().fillna(0).astype(int)
Out[3]:
Event Cost
Location HK LDN HK LDN
2014-08-25 21:00:00 1 1 20 24
2014-08-25 22:00:00 0 2 0 43