pandas dataframe groupby datetime mois


90

Considérez un fichier csv:

string,date,number
a string,2/5/11 9:16am,1.0
a string,3/5/11 10:44pm,2.0
a string,4/22/11 12:07pm,3.0
a string,4/22/11 12:10pm,4.0
a string,4/29/11 11:59am,1.0
a string,5/2/11 1:41pm,2.0
a string,5/2/11 2:02pm,3.0
a string,5/2/11 2:56pm,4.0
a string,5/2/11 3:00pm,5.0
a string,5/2/14 3:02pm,6.0
a string,5/2/14 3:18pm,7.0

Je peux lire ceci et reformater la colonne de date au format datetime:

b=pd.read_csv('b.dat')
b['date']=pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')

J'ai essayé de regrouper les données par mois. Il semble qu'il devrait y avoir un moyen évident d'accéder au mois et de le regrouper. Mais je n'arrive pas à le faire. Quelqu'un sait-il comment?

Ce que j'essaye actuellement est de réindexer par la date:

b.index=b['date']

Je peux accéder au mois comme ceci:

b.index.month

Cependant, je n'arrive pas à trouver une fonction à regrouper par mois.

Réponses:


174

J'ai réussi à le faire:

b = pd.read_csv('b.dat')
b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')
b.groupby(by=[b.index.month, b.index.year])

Ou

b.groupby(pd.Grouper(freq='M'))  # update for v0.21+

51
Je pense que les moyens les plus pandoniques sont d'utiliser resample(quand il fournit les fonctionnalités dont vous avez besoin) ou d'utiliser un TimeGrouper:df.groupby(pd.TimeGrouper(freq='M'))
— Karl D.

10
pour obtenir le résultat DataFrame somme ou moyenne, df.groupby(pd.TimeGrouper(freq='M')).sum()oudf.groupby(pd.TimeGrouper(freq='M')).mean()
— Alexandre

9
pd.TimeGroupera été déconseillé en faveur de pd.Grouper, qui est un peu plus flexible mais prend toujours freqet levelarguments.
— BallpointBen

la première méthode ne semble pas fonctionner. Il donne l'erreur 'L'objet Série n'a pas d'attribut' mois '' pour une Série créée via to_datetime.
— ely

1
@ely La réponse repose implicitement sur les lignes de la question d'origine où best donné un index après avoir été lu à partir de CSV. Ajoutez b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')après la ligne b = pd.read_csv('b.dat'). [J'ai également modifié la réponse.]
— goodside

71

(mise à jour: 2018)

Notez qu'il pd.Timegrouperest amorti et sera supprimé. Utilisez à la place:

 df.groupby(pd.Grouper(freq='M'))

2
Trouvez la documentation de Grouper ici et les spécifications de fréquence ( freq=...) ici . Quelques exemples sont freq=Ddes jours , freq=Bpour jours ouvrables , freq=Wpour semaines ou même freq=Qpour les quarts .
— Kim

1
J'ai trouvé utile d'utiliser 'key' pour éviter d'avoir à réindexer le df, comme suit: df.groupby (pd.Grouper (key = 'your_date_column', freq = 'M'))
— Edward

10

Une solution qui évite MultiIndex est de créer une nouvelle datetimecolonne en définissant le jour = 1. Regrouper ensuite par cette colonne. Exemple trivial ci-dessous.

df = pd.DataFrame({'Date': pd.to_datetime(['2017-10-05', '2017-10-20']),
                   'Values': [5, 10]})

# normalize day to beginning of month
df['YearMonth'] = df['Date'] - pd.offsets.MonthBegin(1)

# two alternative methods
df['YearMonth'] = df['Date'] - pd.to_timedelta(df['Date'].dt.day-1, unit='D')
df['YearMonth'] = df['Date'].map(lambda dt: dt.replace(day=1))

g = df.groupby('YearMonth')

res = g['Values'].sum()

# YearMonth
# 2017-10-01    15
# Name: Values, dtype: int64

L'avantage subtil de cette solution est que, contrairement à ce que pd.Grouperl'index du mérou est normalisé au début de chaque mois plutôt qu'à la fin, vous pouvez facilement extraire des groupes via get_group:

some_group = g.get_group('2017-10-01')

Le calcul du dernier jour d'octobre est un peu plus fastidieux. pd.Grouper, à partir de la version 0.23, prend en charge un conventionparamètre, mais cela n'est applicable que pour un PeriodIndexgroupeur.


8

Solution légèrement alternative à @ jpp mais sortie d'une YearMonthchaîne:

df['YearMonth'] = pd.to_datetime(df['Date']).apply(lambda x: '{year}-{month}'.format(year=x.year, month=x.month))

res = df.groupby('YearMonth')['Values'].sum()
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.