working with python datetime numpy pandas

python - with - to datetime pandas format



Conversión entre datetime, Timestamp y datetime64 (12)

Algunas soluciones funcionan bien para mí, pero numpy eliminará algunos parámetros. La solución que me funciona mejor es leer la fecha como fecha y hora de pandas y excretar explícitamente el año, mes y día de un objeto pandas. El siguiente código funciona para la situación más común.

def format_dates(dates): dt = pd.to_datetime(dates) try: return [datetime.date(x.year, x.month, x.day) for x in dt] except TypeError: return datetime.date(dt.year, dt.month, dt.day)

¿Cómo convierto un objeto numpy.datetime64 a datetime.datetime (o Timestamp )?

En el siguiente código, creo un objeto datetime, timestamp y datetime64.

import datetime import numpy as np import pandas as pd dt = datetime.datetime(2012, 5, 1) # A strange way to extract a Timestamp object, there''s surely a better way? ts = pd.DatetimeIndex([dt])[0] dt64 = np.datetime64(dt) In [7]: dt Out[7]: datetime.datetime(2012, 5, 1, 0, 0) In [8]: ts Out[8]: <Timestamp: 2012-05-01 00:00:00> In [9]: dt64 Out[9]: numpy.datetime64(''2012-05-01T01:00:00.000000+0100'')

Nota: es fácil obtener la fecha y hora de la marca de tiempo:

In [10]: ts.to_datetime() Out[10]: datetime.datetime(2012, 5, 1, 0, 0)

Pero, ¿cómo extraemos datetime o Timestamp de un numpy.datetime64 ( dt64 )?

.

Actualización: un ejemplo un tanto desagradable en mi conjunto de datos (quizás el ejemplo motivador) parece ser:

dt64 = numpy.datetime64(''2002-06-28T01:00:00.000000000+0100'')

que debería ser datetime.datetime(2002, 6, 28, 1, 0) y no un largo (!) ( 1025222400000000000L ) ...


Bienvenido al infierno.

Solo puedes pasar un objeto datetime64 a pandas.Timestamp :

In [16]: Timestamp(numpy.datetime64(''2012-05-01T01:00:00.000000'')) Out[16]: <Timestamp: 2012-05-01 01:00:00>

Noté que esto no funciona bien en NumPy 1.6.1:

numpy.datetime64(''2012-05-01T01:00:00.000000+0100'')

Además, se puede usar pandas.to_datetime (esto está fuera de la versión dev, no se ha verificado v0.9.1):

In [24]: pandas.to_datetime(''2012-05-01T01:00:00.000000+0100'') Out[24]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))


Creo que podría haber un esfuerzo más consolidado en una respuesta para explicar mejor la relación entre el módulo datetime de Python, datetime64 / timedelta64 de numpy y los objetos Timestamp / Timedelta de pandas.

La biblioteca estándar de datetime de Python

La biblioteca estándar de datetime tiene cuatro objetos principales

  • tiempo - solo tiempo, medido en horas, minutos, segundos y microsegundos
  • fecha - solo año, mes y día
  • datetime - Todos los componentes de hora y fecha
  • timedelta - Una cantidad de tiempo con una unidad máxima de días

Crea estos cuatro objetos.

>>> import datetime >>> datetime.time(hour=4, minute=3, second=10, microsecond=7199) datetime.time(4, 3, 10, 7199) >>> datetime.date(year=2017, month=10, day=24) datetime.date(2017, 10, 24) >>> datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199) datetime.datetime(2017, 10, 24, 4, 3, 10, 7199) >>> datetime.timedelta(days=3, minutes = 55) datetime.timedelta(3, 3300) >>> # add timedelta to datetime >>> datetime.timedelta(days=3, minutes = 55) + / datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199) datetime.datetime(2017, 10, 27, 4, 58, 10, 7199)

Objetos datetime64 y timedelta64 de NumPy

NumPy no tiene objetos de fecha y hora separados, solo un objeto datetime64 para representar un momento en el tiempo. El objeto datetime del módulo datetime tiene una precisión de microsegundos (una millonésima de segundo). El objeto datetime64 de NumPy le permite establecer su precisión desde horas hasta attosegundos (10 ^ -18). Su constructor es más flexible y puede tomar una variedad de entradas.

Construye los objetos datetime64 y timedelta64 de NumPy

Pase un entero con una cadena para las unidades. Ver todas las unidades aquí . Se convierte a tantas unidades después de la época de UNIX: 1 de enero de 1970

>>> np.datetime64(5, ''ns'') numpy.datetime64(''1970-01-01T00:00:00.000000005'') >>> np.datetime64(1508887504, ''s'') numpy.datetime64(''2017-10-24T23:25:04'')

También puede utilizar cadenas siempre que estén en formato ISO 8601.

>>> np.datetime64(''2017-10-24'') numpy.datetime64(''2017-10-24'')

Timedeltas tiene una sola unidad

>>> np.timedelta64(5, ''D'') # 5 days >>> np.timedelta64(10, ''h'') 10 hours

También puede crearlos restando dos objetos datetime64

>>> np.datetime64(''2017-10-24T05:30:45.67'') - np.datetime64(''2017-10-22T12:35:40.123'') numpy.timedelta64(147305547,''ms'')

Pandas Timestamp y Timedelta construyen mucha más funcionalidad sobre NumPy

Una marca de tiempo de pandas es un momento en el tiempo muy similar a una fecha y hora pero con mucha más funcionalidad. Puedes construirlos con pd.Timestamp o pd.to_datetime .

>>> pd.Timestamp(1239.1238934) #defautls to nanoseconds Timestamp(''1970-01-01 00:00:00.000001239'') >>> pd.Timestamp(1239.1238934, unit=''D'') # change units Timestamp(''1973-05-24 02:58:24.355200'') >>> pd.Timestamp(''2017-10-24 05'') # partial strings work Timestamp(''2017-10-24 05:00:00'')

pd.to_datetime funciona de manera muy similar (con algunas opciones más) y puede convertir una lista de cadenas en marcas de tiempo.

>>> pd.to_datetime(''2017-10-24 05'') Timestamp(''2017-10-24 05:00:00'') >>> pd.to_datetime([''2017-1-1'', ''2017-1-2'']) DatetimeIndex([''2017-01-01'', ''2017-01-02''], dtype=''datetime64[ns]'', freq=None)

Convertir datetime de Python en datetime64 y marca de tiempo

>>> dt = datetime.datetime(year=2017, month=10, day=24, hour=4, minute=3, second=10, microsecond=7199) >>> np.datetime64(dt) numpy.datetime64(''2017-10-24T04:03:10.007199'') >>> pd.Timestamp(dt) # or pd.to_datetime(dt) Timestamp(''2017-10-24 04:03:10.007199'')

Convertir numpy datetime64 a datetime y Timestamp

>>> dt64 = np.datetime64(''2017-10-24 05:34:20.123456'') >>> unix_epoch = np.datetime64(0, ''s'') >>> one_second = np.timedelta64(1, ''s'') >>> seconds_since_epoch = (dt64 - unix_epoch) / one_second >>> seconds_since_epoch 1508823260.123456 >>> datetime.datetime.utcfromtimestamp(seconds_since_epoch) >>> datetime.datetime(2017, 10, 24, 5, 34, 20, 123456)

Convertir a marca de tiempo

>>> pd.Timestamp(dt64) Timestamp(''2017-10-24 05:34:20.123456'')

Convertir de marca de tiempo a datetime y datetime64

Esto es bastante fácil ya que las marcas de tiempo de los pandas son muy poderosas.

>>> ts = pd.Timestamp(''2017-10-24 04:24:33.654321'') >>> ts.to_pydatetime() # Python''s datetime datetime.datetime(2017, 10, 24, 4, 24, 33, 654321) >>> ts.to_datetime64() numpy.datetime64(''2017-10-24T04:24:33.654321000'')


Este post ha estado activo durante 4 años y todavía tuve problemas con este problema de conversión, por lo que el problema sigue activo en 2017 en cierto sentido. Me sorprendió un poco que la documentación numpy no ofrezca fácilmente un algoritmo de conversión simple, pero esa es otra historia.

Me he encontrado con otra forma de hacer la conversión que solo involucra módulos numpy y datetime , no requiere la importación de pandas, lo que me parece una gran cantidad de código para una conversión tan simple. Noté que datetime64.astype(datetime.datetime) devolverá un objeto datetime.datetime si el datetime64 original está en unidades de microsegundos mientras que otras unidades devuelven una marca de tiempo de entero. Utilizo el módulo xarray para la E / S de datos de archivos Netcdf que usa el datetime64 en unidades de nanosegundos que hacen que la conversión falle a menos que primero convierta a unidades de microsegundos. Aquí está el código de conversión de ejemplo,

import numpy as np import datetime def convert_datetime64_to_datetime( usert: np.datetime64 )->datetime.datetime: t = np.datetime64( usert, ''us'').astype(datetime.datetime) return t

Solo se probó en mi máquina, que es Python 3.6 con una distribución reciente de Anaconda 2017. Solo he analizado la conversión escalar y no he comprobado las conversiones basadas en matrices, aunque supongo que será bueno. Tampoco he mirado el código fuente de datpy 64 numpy para ver si la operación tiene sentido o no.


Para convertir numpy.datetime64 en un objeto datetime que representa el tiempo en UTC en numpy-1.8 :

>>> from datetime import datetime >>> import numpy as np >>> dt = datetime.utcnow() >>> dt datetime.datetime(2012, 12, 4, 19, 51, 25, 362455) >>> dt64 = np.datetime64(dt) >>> ts = (dt64 - np.datetime64(''1970-01-01T00:00:00Z'')) / np.timedelta64(1, ''s'') >>> ts 1354650685.3624549 >>> datetime.utcfromtimestamp(ts) datetime.datetime(2012, 12, 4, 19, 51, 25, 362455) >>> np.__version__ ''1.8.0.dev-7b75899''

El ejemplo anterior asume que np.datetime64 interpreta un objeto de fecha y hora ingenuo como tiempo en UTC.

Para convertir datetime a np.datetime64 y viceversa ( numpy-1.6 ):

>>> np.datetime64(datetime.utcnow()).astype(datetime) datetime.datetime(2012, 12, 4, 13, 34, 52, 827542)

Funciona tanto en un solo objeto np.datetime64 como en una matriz numpy de np.datetime64.

Piense en np.datetime64 de la misma manera que lo haría en np.int8, np.int16, etc. y aplique los mismos métodos para convertir entre objetos de Python, como int, datetime y los objetos numpy correspondientes.

Tu "ejemplo desagradable" funciona correctamente:

>>> from datetime import datetime >>> import numpy >>> numpy.datetime64(''2002-06-28T01:00:00.000000000+0100'').astype(datetime) datetime.datetime(2002, 6, 28, 0, 0) >>> numpy.__version__ ''1.6.2'' # current version available via pip install numpy

Puedo reproducir el valor long en numpy-1.8.0 instalado como:

pip install git+https://github.com/numpy/numpy.git#egg=numpy-dev

El mismo ejemplo:

>>> from datetime import datetime >>> import numpy >>> numpy.datetime64(''2002-06-28T01:00:00.000000000+0100'').astype(datetime) 1025222400000000000L >>> numpy.__version__ ''1.8.0.dev-7b75899''

Devuelve long porque para numpy.datetime64 tipo .astype(datetime) es equivalente a .astype(object) que devuelve el entero Python ( long ) en numpy-1.8 .

Para obtener el objeto datetime usted podría:

>>> dt64.dtype dtype(''<M8[ns]'') >>> ns = 1e-9 # number of seconds in a nanosecond >>> datetime.utcfromtimestamp(dt64.astype(int) * ns) datetime.datetime(2002, 6, 28, 0, 0)

Para obtener datetime64 que usa segundos directamente:

>>> dt64 = numpy.datetime64(''2002-06-28T01:00:00.000000000+0100'', ''s'') >>> dt64.dtype dtype(''<M8[s]'') >>> datetime.utcfromtimestamp(dt64.astype(int)) datetime.datetime(2002, 6, 28, 0, 0)

Los documentos numpy dicen que la API datetime es experimental y puede cambiar en futuras versiones numpy.


Puedes usar el constructor pd.Timestamp. El siguiente diagrama puede ser útil para esto y otras preguntas relacionadas.


Regresé a esta respuesta más veces de las que puedo contar, así que decidí juntar una pequeña clase rápida, que convierte un valor de Numpy datetime64 valor de Python datetime . Espero que ayude a otros por ahí.

from datetime import datetime import pandas as pd class NumpyConverter(object): @classmethod def to_datetime(cls, dt64, tzinfo=None): """ Converts a Numpy datetime64 to a Python datetime. :param dt64: A Numpy datetime64 variable :type dt64: numpy.datetime64 :param tzinfo: The timezone the date / time value is in :type tzinfo: pytz.timezone :return: A Python datetime variable :rtype: datetime """ ts = pd.to_datetime(dt64) if tzinfo is not None: return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, tzinfo=tzinfo) return datetime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second)

Voy a mantener esto en mi bolsa de herramientas, algo me dice que lo necesitaré de nuevo.


Si desea convertir una serie completa de pandas de .to_pydatetime() regulares de Python, también puede usar .to_pydatetime() .

pd.date_range(''20110101'',''20110102'',freq=''H'').to_pydatetime() > [datetime.datetime(2011, 1, 1, 0, 0) datetime.datetime(2011, 1, 1, 1, 0) datetime.datetime(2011, 1, 1, 2, 0) datetime.datetime(2011, 1, 1, 3, 0) ....

También soporta zonas horarias:

pd.date_range(''20110101'',''20110102'',freq=''H'').tz_localize(''UTC'').tz_convert(''Australia/Sydney'').to_pydatetime() [ datetime.datetime(2011, 1, 1, 11, 0, tzinfo=<DstTzInfo ''Australia/Sydney'' EST+11:00:00 DST>) datetime.datetime(2011, 1, 1, 12, 0, tzinfo=<DstTzInfo ''Australia/Sydney'' EST+11:00:00 DST>) ....


Una opción es usar str , y luego to_datetime (o similar):

In [11]: str(dt64) Out[11]: ''2012-05-01T01:00:00.000000+0100'' In [12]: pd.to_datetime(str(dt64)) Out[12]: datetime.datetime(2012, 5, 1, 1, 0, tzinfo=tzoffset(None, 3600))

Nota: no es igual a dt porque se ha vuelto "offset-aware" :

In [13]: pd.to_datetime(str(dt64)).replace(tzinfo=None) Out[13]: datetime.datetime(2012, 5, 1, 1, 0)

Esto parece poco elegante.

.

Actualización: esto puede tratar con el "ejemplo desagradable":

In [21]: dt64 = numpy.datetime64(''2002-06-28T01:00:00.000000000+0100'') In [22]: pd.to_datetime(str(dt64)).replace(tzinfo=None) Out[22]: datetime.datetime(2002, 6, 28, 1, 0)


de hecho, todos estos tipos de fecha y hora pueden ser difíciles y potencialmente problemáticos (deben mantener un seguimiento cuidadoso de la información de la zona horaria). esto es lo que he hecho, aunque admito que me preocupa que al menos parte de esto no sea "por diseño". Además, esto se puede hacer un poco más compacto según sea necesario. comenzando con un numpy.datetime64 dt_a:

dt_a

numpy.datetime64 (''2015-04-24T23: 11: 26.270000-0700'')

dt_a1 = dt_a.tolist () # produce un objeto datetime en UTC, pero sin tzinfo

dt_a1

datetime.datetime (2015, 4, 25, 6, 11, 26, 270000)

# now, make your "aware" datetime:

dt_a2 = datetime.datetime (* list (dt_a1.timetuple () [: 6]) + [dt_a1.microsecond], tzinfo = pytz.timezone (''UTC''))

... y por supuesto, eso se puede comprimir en una línea según sea necesario.


>>> dt64.tolist() datetime.datetime(2012, 5, 1, 0, 0)

Para DatetimeIndex , la lista de tolist devuelve una lista de objetos de datetime . Para un solo objeto datetime64 devuelve un solo objeto datetime .


import numpy as np import pandas as pd def np64toDate(np64): return pd.to_datetime(str(np64)).replace(tzinfo=None).to_datetime()

Utilice esta función para obtener objetos nativos de fecha y hora de Pythons.