Mantenga solo la parte de fecha cuando use pandas.to_datetime

201

Utilizo pandas.to_datetimepara analizar las fechas en mis datos. Pandas por defecto representa las fechas con datetime64[ns]aunque las fechas son todas diarias. Me pregunto si hay una forma elegante / inteligente de convertir las fechas datetime.dateo datetime64[D]para que, cuando escribo los datos en CSV, no se agreguen las fechas 00:00:00. Sé que puedo convertir el tipo manualmente elemento por elemento:

[dt.to_datetime().date() for dt in df.dates]

Pero esto es realmente lento ya que tengo muchas filas y de alguna manera frustra el propósito de usar pandas.to_datetime. ¿Hay alguna forma de convertir la dtypecolumna completa de una vez? O bien, ¿ pandas.to_datetimeadmite una especificación de precisión para poder deshacerme del tiempo mientras trabajo con datos diarios?

jpp
fuente
2
No conozco un buen camino, pero df.dates.apply(lambda x: x.date()) debería ser al menos un poco más rápido. también eche un vistazo a github.com/pydata/pandas/issues/2583
root
1
Consideraría estas dos preguntas como diferentes. El posible duplicado al que se refiere tiene como objetivo dividir la parte de fecha y la parte de hora de una columna de fecha y hora. Esta pregunta está motivada al convertir toda la columna a la vez. Imagine que tiene un marco de datos con 20 columnas que representan fechas. No querrá especificar qué columnas escribir en csv, como se sugiere en la otra pregunta.
1
Esto no es compatible en este momento (@root apunta a la posible mejora), ¿cuál es el propósito de hacer esto, al escribir en csv?
Jeff
3
Bueno, a menudo tenemos que escribir datos en archivos csv para que otros programas los lean. Las 00:00:00 redundantes solo dificultan el procesamiento en general, especialmente cuando estoy trabajando con datos puramente diarios.

Respuestas:

286

Desde la versión, 0.15.0esto ahora se puede hacer fácilmente usando .dtpara acceder solo al componente de fecha:

df['just_date'] = df['dates'].dt.date

Lo anterior devuelve un datetime.datedtype, si desea tener un datetime64entonces puede simplemente normalizeel componente de tiempo a medianoche para que establezca todos los valores en 00:00:00:

df['normalised_date'] = df['dates'].dt.normalize()

Esto mantiene el dtype como datetime64pero la pantalla muestra solo el datevalor.

EdChum
fuente
33

Solución simple:

df['date_only'] = df['date_time_column'].dt.date
Gil Baggio
fuente
Solo una advertencia, esto cambia el tipo a objeto. Por lo tanto, necesitaría un tipo ('datetime64') para mantener la coherencia.
misantroop
25

Si bien voté por la respuesta de EdChum, que es la respuesta más directa a la pregunta que planteó el OP, en realidad no resuelve el problema de rendimiento (todavía se basa en datetimeobjetos de Python y, por lo tanto, no se vectorizará ninguna operación en ellos, es decir, será lento)

Una mejor alternativa de rendimiento es usar df['dates'].dt.floor('d'). Estrictamente hablando, no "mantiene solo una parte de la fecha", ya que solo establece el tiempo para 00:00:00. Pero funciona como lo desea el OP cuando, por ejemplo:

  • impresión en pantalla
  • guardar en csv
  • usando la columna para groupby

... y es mucho más eficiente, ya que la operación está vectorizada.

EDIT: de hecho, la respuesta habría preferido que el de OP es probablemente "las versiones recientes de pandasqué no escriben el tiempo para csv si es 00:00:00para todas las observaciones".

Pietro Battiston
fuente
Lamentablemente to_jsontodavía escribe el completo 00:00:00.
IanS
@IanS te refieres al usar date_format='iso'?! Por defecto, solo genera segundos desde la época.
Pietro Battiston
Sí, a eso me refería.
IanS
Esto es más rápido que dt.normalize()en series de más de unos cientos de elementos.
C8H10N4O2
16

Los pandas DatetimeIndexy Seriestienen un método llamado normalizeque hace exactamente lo que quieres.

Puedes leer más sobre esto en esta respuesta .

Se puede usar como ser.dt.normalize()

j08lue
fuente
15

Pandas v0.13 +: Usar to_csvcon date_formatparámetro

Evite, cuando sea posible, convertir su datetime64[ns]serie en una objectserie dtype de datetime.dateobjetos. Este último, a menudo construido utilizandopd.Series.dt.date , se almacena como una matriz de punteros y es ineficiente en relación con una serie pura basada en NumPy.

Como su preocupación es el formato al escribir en CSV , simplemente use el date_formatparámetro de to_csv. Por ejemplo:

df.to_csv(filename, date_format='%Y-%m-%d')

Vea las strftimedirectivas de Python para las convenciones de formato.

jpp
fuente
8

Esta es una manera simple de extraer la fecha:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)
Mani Abi Anand
fuente
El OP ya está utilizando el método .date () en su pregunta, por lo que esta solución no responde a su pregunta, pero me pareció útil ver un ejemplo simple de uso del método date () solo como referencia.
Nic Scozzaro
5

Convirtiendo a datetime64[D]:

df.dates.values.astype('M8[D]')

Aunque reasignar eso a una columna DataFrame lo revertirá a [ns].

Si querías real datetime.date:

dt = pd.DatetimeIndex(df.dates)
dates = np.array([datetime.date(*date_tuple) for date_tuple in zip(dt.year, dt.month, dt.day)])
Dale Jung
fuente
3
Si está utilizando un tipo ('M8 [D]'), transforma los valores faltantes en la fecha de origen, 1970-1-1. Probablemente sea mejor usar pandas.to_datetime () hoy en día.
Stewbaca
1
Nota para cualquiera que incluya habitualmente el módulo de fecha y hora, ya que dteste fragmento de respuesta sobrescribirá ese módulo. @ Dale-Jung, tal vez podría cambiar la línea a algo así como dt_index
yeliabsalohcin
También estoy encontrando un problema por el que la próxima vez que lo intento y añadir una nueva fila a través del df.loc[date]método, los revierte Vuelta a una marca de tiempo, es decir, las comparaciones posteriores ya no funcionan
yeliabsalohcin
3

Simplemente dando una respuesta más actualizada en caso de que alguien vea esta publicación anterior.

Agregar "utc = False" al convertir a datetime eliminará el componente de zona horaria y mantendrá solo la fecha en un tipo de datos datetime64 [ns].

pd.to_datetime(df['Date'], utc=False)

Podrá guardarlo en Excel sin obtener el error "ValueError: Excel no admite fechas y horas con zonas horarias. Asegúrese de que las horas no sean conscientes de la zona horaria antes de escribir en Excel".

ingrese la descripción de la imagen aquí

Katekarin
fuente
Esto por alguna razón falla después de aplicar cualquier función agregada con la columna.
RaphX
0

Quería poder cambiar el tipo de un conjunto de columnas en un marco de datos y luego eliminar la hora que guarda el día. round (), floor (), ceil () todo el trabajo

df[date_columns] = df[date_columns].apply(pd.to_datetime)
df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
Climbs_lika_Spyder
fuente