web-dev-qa-db-fra.com

Extraire uniquement le mois et l’année séparément de la colonne Pandas Datetime

J'ai un Dataframe, df, avec la colonne suivante:

df['ArrivalDate'] =
...
936   2012-12-31
938   2012-12-29
965   2012-12-31
966   2012-12-31
967   2012-12-31
968   2012-12-31
969   2012-12-31
970   2012-12-29
971   2012-12-31
972   2012-12-29
973   2012-12-29
...

Les éléments de la colonne sont pandas.tslib.Timestamp.

Je veux juste inclure l'année et le mois. Je pensais qu'il y aurait un moyen simple de le faire, mais je ne peux pas le comprendre.

Voici ce que j'ai essayé:

df['ArrivalDate'].resample('M', how = 'mean')

J'ai eu l'erreur suivante:

Only valid with DatetimeIndex or PeriodIndex 

Puis j'ai essayé:

df['ArrivalDate'].apply(lambda(x):x[:-2])

J'ai eu l'erreur suivante:

'Timestamp' object has no attribute '__getitem__' 

Aucune suggestion?

Edit: Je l'ai en quelque sorte compris.

df.index = df['ArrivalDate']

Ensuite, je peux rééchantillonner une autre colonne à l'aide de l'index.

Mais j'aimerais quand même une méthode pour reconfigurer toute la colonne. Des idées?

158
monkeybiz7

Vous pouvez accéder directement aux attributs year et month ou demander un datetime.datetime:

In [15]: t = pandas.tslib.Timestamp.now()

In [16]: t
Out[16]: Timestamp('2014-08-05 14:49:39.643701', tz=None)

In [17]: t.to_pydatetime() #datetime method is deprecated
Out[17]: datetime.datetime(2014, 8, 5, 14, 49, 39, 643701)

In [18]: t.day
Out[18]: 5

In [19]: t.month
Out[19]: 8

In [20]: t.year
Out[20]: 2014

Une façon de combiner année et mois consiste à créer un entier les encodant, tel que: 201408 pour août 2014. Le long d'une colonne entière, vous pouvez le faire comme suit:

df['YearMonth'] = df['ArrivalDate'].map(lambda x: 100*x.year + x.month)

ou de nombreuses variantes de ceux-ci.

Cependant, je ne suis pas un grand partisan de cela, car cela rend l’alignement et l’arithmétique des dates plus difficiles et plus pénibles pour les autres utilisateurs qui rencontrent votre code ou vos données sans respecter la même convention. Une meilleure solution consiste à choisir une convention du jour du mois, telle que le jour de la semaine, le premier jour, etc., sauf les jours fériés, et laissez les données au format date/heure avec la convention de date choisie.

Le module calendar est utile pour obtenir la valeur numérique de certains jours tels que le dernier jour de la semaine. Ensuite, vous pourriez faire quelque chose comme:

import calendar
import datetime
df['AdjustedDateToEndOfMonth'] = df['ArrivalDate'].map(
    lambda x: datetime.datetime(
        x.year,
        x.month,
        max(calendar.monthcalendar(x.year, x.month)[-1][:5])
    )
)

Si vous cherchez un moyen de résoudre le problème plus simple du formatage de la colonne datetime en une représentation sous forme de chaîne, vous pouvez simplement utiliser la fonction strftime du datetime.datetime classe, comme ceci:

In [5]: df
Out[5]: 
            date_time
0 2014-10-17 22:00:03

In [6]: df.date_time
Out[6]: 
0   2014-10-17 22:00:03
Name: date_time, dtype: datetime64[ns]

In [7]: df.date_time.map(lambda x: x.strftime('%Y-%m-%d'))
Out[7]: 
0    2014-10-17
Name: date_time, dtype: object
119
ely

Si vous voulez de nouvelles colonnes indiquant l'année et le mois séparément, vous pouvez le faire:

df['year'] = pd.DatetimeIndex(df['ArrivalDate']).year
df['month'] = pd.DatetimeIndex(df['ArrivalDate']).month

ou...

df['year'] = df['ArrivalDate'].dt.year
df['month'] = df['ArrivalDate'].dt.month

Ensuite, vous pouvez les combiner ou travailler avec eux tels qu’ils sont.

227
KieranPC

Meilleur moyen trouvé !!

le df['date_column'] doit être au format date/heure.

df['month_year'] = df['date_column'].dt.to_period('M')

Vous pouvez également utiliser D pour le jour, 2M pendant 2 mois, etc. pour différents intervalles d'échantillonnage, et si vous avez des données de série chronologique avec horodatage, nous pouvons utiliser des intervalles d'échantillonnage granulaires tels que 45Min pendant 45 min, 15Min pour échantillonnage de 15 min, etc.

188
Pankaj Kabra

Si vous voulez que la paire mois-année soit unique, utiliser apply est plutôt élégant.

    df['mnth_yr'] = df['date_column'].apply(lambda x: x.strftime('%B-%Y'))     

sorties mois-année dans une colonne.

n'oubliez pas de changer d'abord le format en date-heure avant, j'oublie généralement: |

    df['date_column'] = pd.to_datetime(df['date_column'])
27
Pankaj Kabra

Extraire l'année, dites de ['2018-03-04']

df['Year'] = pd.DatetimeIndex(df['date']).year  

Le df ['Year'] crée une nouvelle colonne. Tandis que si vous voulez extraire le mois, utilisez simplement .month

10
Douglas

Grâce à jaknap32 , j'ai voulu agréger les résultats par année et par mois, donc cela a fonctionné:

df_join['YearMonth'] = df_join['timestamp'].apply(lambda x:x.strftime('%Y%m'))

La sortie était soignée:

0    201108
1    201108
2    201108
5
Subspacian

Vous pouvez d’abord convertir vos chaînes de date avec pandas.to_datetime , ce qui vous donne accès à toutes les installations numpy datetime et timedelta . Par exemple:

df['ArrivalDate'] = pandas.to_datetime(df['ArrivalDate'])
df['Month'] = df['ArrivalDate'].values.astype('datetime64[M]')
4
Juan A. Navarro

la solution de @ KieranPC est l'approche correcte pour les pandas, mais elle n'est pas facilement extensible pour des attributs arbitraires. Pour cela, vous pouvez utiliser getattr dans une compréhension du générateur et combiner en utilisant pd.concat :

_list_of_dates = ['2012-12-31', '2012-12-29', '2012-12-30']
df = pd.DataFrame({'ArrivalDate': pd.to_datetime(list_of_dates)})

L = ['year', 'month', 'day', 'dayofweek', 'dayofyear', 'weekofyear', 'quarter']
df = df.join(pd.concat((getattr(df['ArrivalDate'].dt, i).rename(i) for i in L), axis=1))

print(df)

  ArrivalDate  year  month  day  dayofweek  dayofyear  weekofyear  quarter
0  2012-12-31  2012     12   31          0        366           1        4
1  2012-12-29  2012     12   29          5        364          52        4
2  2012-12-30  2012     12   30          6        365          52        4
_
2
jpp
df['year_month']=df.datetime_column.apply(lambda x: str(x)[:7])

Cela a bien fonctionné pour moi, je ne pensais pas que pandas interpréterait la date de chaîne résultante comme une date. amour pandas!

1
TICH

Il y a deux étapes pour extraire une année pour tout le cadre de données sans utiliser la méthode apply.

Step1

convertir la colonne en date/heure:

df['ArrivalDate']=pd.to_datetime(df['ArrivalDate'], format='%Y-%m-%d')

Step2

extraire l'année ou le mois en utilisant la méthode DatetimeIndex()

 pd.DatetimeIndex(df['ArrivalDate']).year
0
abdellah el atouani