2012-11-30 14 views
38

Ho un array di tipo datetime64:Get anno, mese o giorno dalle datetime64 NumPy

dates = np.datetime64(['2010-10-17', '2011-05-13', "2012-01-15"]) 

Esiste un modo migliore di loop attraverso ogni elemento solo per ottenere np.array di anni:

years = f(dates) 
#output: 
array([2010, 2011, 2012], dtype=int8) #or dtype = string 

Sto usando la versione numpy stabile 1.6.2.

+0

Che cosa si intende quando si scrive "F (date)". Cosa fa "f()"? – MikeyE

risposta

28

Come datetime non è stabile in NumPy userei panda per questo:

In [52]: import pandas as pd 

In [53]: dates = pd.DatetimeIndex(['2010-10-17', '2011-05-13', "2012-01-15"]) 

In [54]: dates.year 
Out[54]: array([2010, 2011, 2012], dtype=int32) 

Pandas utilizza datetime NumPy internamente, ma sembra evitare le scarsità, che NumPy ha fino ad ora.

+4

Questo mi sta dando risultati errati per il mese con numpy 1.7.1 e panda 0.12.0. Tuttavia, 'Series (date) .apply (lambda x: x.month)' sembra funzionare. – dmvianna

+0

Nessun problema qui con le stesse versioni. Se sbagli davvero risultati, dovresti aprire un problema con i panda. – bmu

+0

Oh, in realtà ho usato 'pd.DatetimeIndex (np.datetime64 (['2010-10-17', '2011-05-13'," 2012-01-15 "]))' – dmvianna

1

Se si esegue l'aggiornamento a numpy 1.7 (dove datetime è ancora etichettato come sperimentale), dovrebbe funzionare quanto segue.

dates/np.timedelta64(1,'Y') 
+1

Si noti che a partire da 1.9 questo metodo non funziona. La divisione ha lo scopo di convertire l'intervallo di tempo in un numero in virgola mobile di anni. Non estrae l'attributo dell'anno di una data. – jdr5ca

0

Non c'è modo diretto per farlo ancora, purtroppo, ma ci sono un paio di modi indiretti:

[dt.year for dt in dates.astype(object)] 

o

[datetime.datetime.strptime(repr(d), "%Y-%m-%d %H:%M:%S").year for d in dates] 

entrambi ispirati dagli esempi here.

Entrambi funzionano per Numepy 1.6.1. Potrebbe essere necessario fare un po 'più attenzione con il secondo, dal momento che repr() per il datetime64 potrebbe avere una parte frazione dopo un punto decimale.

+0

Questo non funziona in python 3.5, numpy 1.11, per lo stesso motivo del mio commento su [risposta di Ncik] (http://stackoverflow.com/a/35281829/210945) – naught101

16

Trovo che i seguenti trucchi diano tra 2 e 4x aumento di velocità rispetto al metodo panda descritto sopra (ad esempio pd.DatetimeIndex(dates).year ecc.). La velocità di [dt.year for dt in dates.astype(object)] trovo simile al metodo panda. Anche questi trucchi possono essere applicati direttamente alle ndarrays di qualsiasi forma (2D, 3D ecc)

dates = np.arange(np.datetime64('2000-01-01'), np.datetime64('2010-01-01')) 
years = dates.astype('datetime64[Y]').astype(int) + 1970 
months = dates.astype('datetime64[M]').astype(int) % 12 + 1 
days = dates - dates.astype('datetime64[M]') + 1 
+0

Questa è una buona soluzione. Sarebbe davvero bello se ci fosse qualcosa di semplice in questo modo in numpy. – naught101

+0

Grazie per aver effettivamente dato una risposta, invece di dire "non dovresti usare , usa invece ". –

4

Ci dovrebbe essere un modo più semplice per fare questo, ma, a seconda di quello che stai cercando di fare, il migliore percorso potrebbe essere quella di convertire in un normale Python datetime object:

datetime64Obj = np.datetime64('2002-07-04T02:55:41-0700') 
print datetime64Obj.astype(object).year 
# 2002 
print datetime64Obj.astype(object).day 
# 4 

sulla base di commenti qui sotto, questo sembra funzionare solo in Python 2.7.x non Python 3.x

+0

E puoi farlo su un intero array usando le operazioni lista [come delineato da @acjay] (http://stackoverflow.com/a/13654502/1304462): '[dt.year per dt in dtime64Array.astype (oggetto) ] ' – Nick

+0

Questo codice funziona, ma se gli dò un diverso np.datetime64 (una data dal mio DataFrame) si valuta a lungo invece di datetime ... anche se io uso astype (datetime.datetime) esplicitamente a lungo. .. strano ... –

+0

@ Mr.WorshipMe non siamo sicuri di questo. Potrebbe essere utile scrivere una versione più dettagliata che mostri un esempio di doppio comportamento. Quindi invialo come una nuova domanda con un link qui. – Nick

0

Utilizzando NumPy versione 1.10.4 e la versione panda 0,17.1,

dates = np.array(['2010-10-17', '2011-05-13', '2012-01-15'], dtype=np.datetime64) 
pd.to_datetime(dates).year 

ottengo quello che stai cercando:

array([2010, 2011, 2012], dtype=int32) 
0

Anon's answer grandi opere per me, ma ho solo bisogno di modificare l'istruzione per days

da:

days = dates - dates.astype('datetime64[M]') + 1

a:

days = dates.astype('datetime64[D]') - dates.astype('datetime64[M]') + 1
+1

Questa risposta dovrebbe probabilmente essere trasformata in un commento (o una modifica) alla risposta di Anon che hai menzionato. – firegurafiku

0

Un'altra possibilità è:

np.datetime64(dates,'Y') - returns - numpy.datetime64('2010') 

o

np.datetime64(dates,'Y').astype(int)+1970 - returns - 2010 

ma funziona solo su valori scalari, non avrà serie

Problemi correlati