Combinar columnas de fecha y hora usando python pandas

113

Tengo un marco de datos de pandas con las siguientes columnas;

Date              Time
01-06-2013      23:00:00
02-06-2013      01:00:00
02-06-2013      21:00:00
02-06-2013      22:00:00
02-06-2013      23:00:00
03-06-2013      01:00:00
03-06-2013      21:00:00
03-06-2013      22:00:00
03-06-2013      23:00:00
04-06-2013      01:00:00

¿Cómo combino datos ['Fecha'] y datos ['Hora'] para obtener lo siguiente? ¿Hay alguna forma de hacerlo usando pd.to_datetime?

Date
01-06-2013 23:00:00
02-06-2013 01:00:00
02-06-2013 21:00:00
02-06-2013 22:00:00
02-06-2013 23:00:00
03-06-2013 01:00:00
03-06-2013 21:00:00
03-06-2013 22:00:00
03-06-2013 23:00:00
04-06-2013 01:00:00
Richie
fuente
Gracias por todas las respuestas. He probado la mayoría de ellos, pero aún cuando agrego esta información de fecha y hora como parte de un marco de datos más grande. La columna de fecha y hora solo muestra la fecha y la información de la hora no se muestra. ¿Debemos entender que el tiempo está escondido allí o se quita?
karthikeyan

Respuestas:

169

Vale la pena mencionar que es posible que haya podido leer esto directamente, por ejemplo, si estaba usando read_csvusing parse_dates=[['Date', 'Time']].

Suponiendo que estas son solo cadenas, simplemente puede agregarlas (con un espacio), lo que le permite aplicar to_datetime:

In [11]: df['Date'] + ' ' + df['Time']
Out[11]:
0    01-06-2013 23:00:00
1    02-06-2013 01:00:00
2    02-06-2013 21:00:00
3    02-06-2013 22:00:00
4    02-06-2013 23:00:00
5    03-06-2013 01:00:00
6    03-06-2013 21:00:00
7    03-06-2013 22:00:00
8    03-06-2013 23:00:00
9    04-06-2013 01:00:00
dtype: object

In [12]: pd.to_datetime(df['Date'] + ' ' + df['Time'])
Out[12]:
0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00
dtype: datetime64[ns]

Nota: sorprendentemente (para mí), esto funciona bien con los NaN convertidos a NaT, pero vale la pena preocuparse de que la conversión (quizás usando el raiseargumento).

Andy Hayden
fuente
6
No sabía acerca de la característica combinación automática, y funciona con múltiples entradas también, como: parse_dates=[['Start date', 'Start time'], ['End date', 'End time']]). Pandas <3
5agado
43

La respuesta aceptada funciona para columnas que son de tipo de datos string. Para completar: me encuentro con esta pregunta al buscar cómo hacer esto cuando las columnas son de tipos de datos: fecha y hora.

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']),1)
jka.ne
fuente
2
No puedo encontrar nada sobre el tipo timed, en pandas. Tengo más bien una timedelta(y una datetime), en cuyo caso solo necesita agregarlas, vea mi respuesta
toto_tico
Cuando 'pd.read_excel' una columna de Excel que Excel identifica como "Hora", los pandas también la leen como "Hora" automáticamente sin que se requiera ningún argumento de análisis. Gracias por esta solucion. +1
Saeed
1
Solo una nota, a partir de pandas 1.0.0 pd.datetime se ha desaprobado y se sugiere simplemente importar explícitamente el datetimemódulo.
CopOnTheRun
16

Puede usar esto para combinar fecha y hora en la misma columna de marco de datos.

import pandas as pd    
data_file = 'data.csv' #path of your file

Leyendo el archivo .csv con columnas fusionadas Date_Time:

data = pd.read_csv(data_file, parse_dates=[['Date', 'Time']]) 

Puede usar esta línea para mantener las otras dos columnas también.

data.set_index(['Date', 'Time'], drop=False)
MK Rana
fuente
1
También puede usar personalizado date_parser, por ejemploparser = lambda date: pd.datetime.strptime(date, '%d-%b-%y %H:%M:%S')
Serendipity
11

Puede convertir las columnas si los tipos son diferentes (fecha y hora y marca de tiempo o str) y usar to_datetime:

df.loc[:,'Date'] = pd.to_datetime(df.Date.astype(str)+' '+df.Time.astype(str))

Resultado:

0   2013-01-06 23:00:00
1   2013-02-06 01:00:00
2   2013-02-06 21:00:00
3   2013-02-06 22:00:00
4   2013-02-06 23:00:00
5   2013-03-06 01:00:00
6   2013-03-06 21:00:00
7   2013-03-06 22:00:00
8   2013-03-06 23:00:00
9   2013-04-06 01:00:00

Mejor,

Chris PERE
fuente
10

No tengo suficiente reputación para comentar sobre jka.ne, así que:

Tuve que modificar la línea de jka.ne para que funcionara:

df.apply(lambda r : pd.datetime.combine(r['date_column_name'],r['time_column_name']).time(),1)

Esto podría ayudar a otros.

Además, he probado un enfoque diferente, usando en replacelugar de combine:

def combine_date_time(df, datecol, timecol):
    return df.apply(lambda row: row[datecol].replace(
                                hour=row[timecol].hour,
                                minute=row[timecol].minute),
                    axis=1)

que en el caso del OP sería:

combine_date_time(df, 'Date', 'Time')

He cronometrado ambos enfoques para un conjunto de datos relativamente grande (> 500.000 filas), y ambos tienen tiempos de ejecución similares, pero el uso combinees más rápido (59 segundos replacefrente a 50 segundos combine).

jabellcu
fuente
5

La respuesta realmente depende de cuáles sean sus tipos de columna . En mi caso, tuve datetimey timedelta.

> df[['Date','Time']].dtypes
Date     datetime64[ns]
Time    timedelta64[ns]

Si este es tu caso, solo necesitas agregar las columnas:

> df['Date'] + df['Time']
toto_tico
fuente
La respuesta aceptada asume cadenas: "Suponiendo que estas son solo cadenas, podría simplemente agregarlas (con un espacio)" . Mis respuestas son para datetimey timedelta. La respuesta principal de alguna manera descubrió que las columnas eran cadenas, o tal vez fue solo la respuesta que funcionó para el que publicó la pregunta.
toto_tico
4

También puede convertir a datetimesin concatenación de cadenas, combinando objetos datetimey timedelta. Combinado con pd.DataFrame.pop, puede eliminar la serie fuente simultáneamente:

df['DateTime'] = pd.to_datetime(df.pop('Date')) + pd.to_timedelta(df.pop('Time'))

print(df)

             DateTime
0 2013-01-06 23:00:00
1 2013-02-06 01:00:00
2 2013-02-06 21:00:00
3 2013-02-06 22:00:00
4 2013-02-06 23:00:00
5 2013-03-06 01:00:00
6 2013-03-06 21:00:00
7 2013-03-06 22:00:00
8 2013-03-06 23:00:00
9 2013-04-06 01:00:00

print(df.dtypes)

DateTime    datetime64[ns]
dtype: object
jpp
fuente
1
¡Gran solución general! Escribí datetime date y type str time y esto funcionó.
gorrión
3

Primero asegúrese de tener los tipos de datos correctos:

df["Date"] = pd.to_datetime(df["Date"])
df["Time"] = pd.to_timedelta(df["Time"])

Entonces puedes combinarlos fácilmente:

df["DateTime"] = df["Date"] + df["Time"]
queise
fuente
2

Usa la combinefunción:

datetime.datetime.combine(date, time)
Stephen
fuente
2

Mi conjunto de datos tuvo datos de resolución de 1 segundo durante unos días y el análisis con los métodos sugeridos aquí fue muy lento. En su lugar usé:

dates = pandas.to_datetime(df.Date, cache=True)
times = pandas.to_timedelta(df.Time)
datetimes  = dates + times

Tenga en cuenta que el uso de cache=Truehace que analizar las fechas sea muy eficiente, ya que solo hay un par de fechas únicas en mis archivos, lo que no es cierto para una columna de fecha y hora combinadas.

tgbrooks
fuente
Eso es lo que haría yo.
Yaakov Bressler
1

DATOS:

<TICKER>, <PER>, <DATE>, <TIME> , <OPEN>, <HIGH>, <LOW>, <CERRAR>, <VOL> SPFB.RTS, 1, 20190103,100100 , 106580.0000000,107260.0000000,106570.0000000 , 107230.0000000,3726

CÓDIGO:

data.columns = ['ticker', 'per', 'date', 'time', 'open', 'high', 'low', 'close', 'vol']    
data.datetime = pd.to_datetime(data.date.astype(str) + ' ' + data.time.astype(str), format='%Y%m%d %H%M%S')
hacknull
fuente