Combinar columnas de fecha y hora usando pandas

6 minutos de lectura

avatar de usuario
rico

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

data = {'Date': ['01-06-2013', '02-06-2013', '02-06-2013', '02-06-2013', '02-06-2013', '03-06-2013', '03-06-2013', '03-06-2013', '03-06-2013', '04-06-2013'],
        'Time': ['23:00:00', '01:00:00', '21:00:00', '22:00:00', '23:00:00', '01:00:00', '21:00:00', '22:00:00', '23:00:00', '01:00:00']}
df = pd.DataFrame(data)

         Date      Time
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

¿Cómo combino datos?[‘Date’] & datos[‘Time’] para obtener lo siguiente? ¿Hay alguna manera 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

avatar de usuario
Andy Hayden

Vale la pena mencionar que es posible que hayas podido leer esto en directamente por ejemplo, si estuviera usando read_csv usando parse_dates=[['Date', 'Time']].

Suponiendo que estas son solo cadenas, simplemente puede agregarlas (con un espacio), lo que le permite usar to_datetimeque funciona sin especificar el format= parámetro

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]

Alternativamente, sin la + ' 'pero el format= se debe usar el parámetro. Además, pandas es bueno para deducir el formato que se va a convertir a un datetimesin embargo, especificar el formato exacto es más rápido.

pd.to_datetime(df['Date'] + df['Time'], format="%m-%d-%Y%H:%M:%S")

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

%%timeit

# sample dataframe with 10000000 rows using df from the OP
df = pd.concat([df for _ in range(1000000)]).reset_index(drop=True)

%%timeit
pd.to_datetime(df['Date'] + ' ' + df['Time'])
[result]:
1.73 s ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
pd.to_datetime(df['Date'] + df['Time'], format="%m-%d-%Y%H:%M:%S")
[result]:
1.33 s ± 9.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

La respuesta aceptada funciona para columnas que son de tipo de datos. string. Para completar: me encuentro con esta pregunta cuando busco 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)

  • No puedo encontrar nada con respecto a la time dtype, en pandas. tengo mas bien un timedelta (y un datetime) en cuyo caso solo necesita agregarlos, vea mi respuesta

    – toto_tico

    15 mayo 2018 a las 14:31

  • Cuando ‘pd.read_excel’ una columna de Excel que Excel identifica como “Tiempo”, pandas también la lee como “Tiempo” automáticamente sin necesidad de ningún argumento de análisis. Gracias por esta solución. +1

    – Said

    14 de octubre de 2018 a las 3:10


  • Solo una nota, a partir de pandas 1.0.0 pd.datetime ha sido desaprobado y se sugiere importar explícitamente el datetime módulo en su lugar.

    – CopOnTheRun

    22 de marzo de 2020 a las 15:22

  • Este método es demasiado lento para grandes conjuntos de datos. Es más rápido convertir ambas columnas en cadenas, unirlas y usar to_datetime.

    – Mykola Zotko

    12 oct 2021 a las 9:52

avatar de usuario
chris pere

Convierta las columnas si los tipos son diferentes (datetime y timestamp o str) y use 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,

  • Esta fue la única opción que pude conseguir para trabajar con Python datetime tipos de módulos. Pero ahora tengo este informe convertido a datetime64[ns]y esto me deja con tipos mixtos en otros lugares, lo que nunca es bueno.

    – xtian

    23 de mayo de 2021 a las 0:27


  • Esta opción es ineficiente en comparación con la respuesta aceptada porque las dos columnas ya son cadenas. Por lo tanto, usando .astype(str) es innecesario (dado el OP). También, df['Date'] = Será suficiente; sin necesidad de .loc (p.ej df.loc[:,'Date'] =)

    –Trenton McKinney

    5 de diciembre de 2021 a las 17:53


avatar de usuario
mk rana

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

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

Lectura del archivo .csv con columnas combinadas 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)

avatar de usuario
jabellcu

No tengo suficiente reputación para comentar en 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 replace en vez 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 usando combine es más rápido (59s para replace contra 50 para combine).

avatar de usuario
trenton mckinney

También puedes convertir a datetime sin concatenación de cadenas, combinando to_datetime y to_timedeltaque crean datetime y timedeltea objetos, respectivamente. Combinado con pd.DataFrame.poppuede eliminar la serie de origen 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

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

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

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

> df['Date'] + df['Time']

  • La respuesta aceptada asume cadenas: “Suponiendo que estas son solo cadenas, simplemente podría agregarlas (con un espacio)”. mis respuestas son para datetime y timedelta. La respuesta principal de alguna manera descubrió que las columnas eran cadenas, o tal vez solo fue la respuesta que funcionó para el que publicó la pregunta.

    – toto_tico

    24 de enero de 2019 a las 9:02

¿Ha sido útil esta solución?