J'ai un pandas.DataFrame
appelé df
qui a un index généré automatiquement, avec une colonne dt
:
df['dt'].dtype, df['dt'][0]
# (dtype('<M8[ns]'), Timestamp('2014-10-01 10:02:45'))
Ce que j'aimerais faire, c'est créer une nouvelle colonne tronquée avec une précision horaire. J'utilise actuellement:
df['dt2'] = df['dt'].apply(lambda L: datetime(L.year, L.month, L.day, L.hour))
Cela fonctionne, donc ça va. Cependant, j'ai une idée, il y a une bonne façon d'utiliser pandas.tseries.offsets
ou en créant un DatetimeIndex
ou similaire.
Donc, si possible, y a-t-il un pandas
de la magie pour le faire?
Dans pandas 0.18.0 et versions ultérieures, il y a datetime floor
, ceil
et - round
méthodes pour arrondir les horodatages à une précision/fréquence fixe donnée. Pour arrondir à la précision horaire, vous pouvez utiliser:
>>> df['dt2'] = df['dt'].dt.floor('h')
>>> df
dt dt2
0 2014-10-01 10:02:45 2014-10-01 10:00:00
1 2014-10-01 13:08:17 2014-10-01 13:00:00
2 2014-10-01 17:39:24 2014-10-01 17:00:00
Voici une autre alternative pour tronquer les horodatages. Contrairement à floor
, il prend en charge la troncature avec une précision telle que l'année ou le mois.
Vous pouvez temporairement ajuster l'unité de précision du NumPy sous-jacent datetime64
type de données, modification de [ns]
à [h]
:
df['dt'].values.astype('<M8[h]')
Cela tronque tout avec une précision horaire. Par exemple:
>>> df
dt
0 2014-10-01 10:02:45
1 2014-10-01 13:08:17
2 2014-10-01 17:39:24
>>> df['dt2'] = df['dt'].values.astype('<M8[h]')
>>> df
dt dt2
0 2014-10-01 10:02:45 2014-10-01 10:00:00
1 2014-10-01 13:08:17 2014-10-01 13:00:00
2 2014-10-01 17:39:24 2014-10-01 17:00:00
>>> df.dtypes
dt datetime64[ns]
dt2 datetime64[ns]
La même méthode devrait fonctionner pour toute autre unité: mois 'M'
, minutes 'm'
, etc:
'<M8[Y]'
'<M8[M]'
'<M8[D]'
'<M8[m]'
'<M8[s]'
Une méthode que j'ai utilisée dans le passé pour atteindre cet objectif était la suivante (assez similaire à ce que vous faites déjà, mais je pensais que je le mettrais là-bas de toute façon):
df['dt2'] = df['dt'].apply(lambda x: x.replace(minute=0, second=0))