Concatenando pandas datetime

Tengo soluciones para esta pregunta, 2 soluciones de hecho, pero no estoy contento con ellas. La razón es que los archivos que estoy tratando de leer tienen alrededor de 12 millones de filas y, al utilizar estas soluciones, se tarda mucho tiempo en procesarlas. Principalmente, la razón es que las soluciones son operaciones fila por fila.

Entonces, leí el archivo así:

In [1]: df = pd.read_csv('C:/Projects/NPMRDS/FHWA_TASK2-4_NJ_09_2013_TT.CSV') df.head() Out [1]: TMC DATE EPOCH Travel_TIME_ALL_VEHICLES Travel_TIME_PASSENGER_VEHICLES Travel_TIME_FREIGHT_TRUCKS 0 103N04152 9252013 211 12 12 NaN 1 103N04152 9262013 0 7 7 NaN 2 103N04152 9032013 177 8 8 NaN 3 103N04152 9042013 176 8 9 7 

Mi problema es con las columnas DATE y EPOCH . Quiero fusionarlos en una sola columna de fecha y hora.

  • La FECHA está en el formato ‘% m% d% Y’ (con el cero inicial faltante)
  • EPOCH es una época de 5 minutos de un día:

     Time EPOCH 00:00:00 => 0 00:05:00 => 1 ... ... 12:00:00 => 144 12:05:00 => 145 ... ... 23:50:00 => 286 23:55:00 => 287 

Lo que quiero es algo como esto:

 In [2]: df.head() Out [2]: TMC DATE_TIME DATE EPOCH Travel_TIME_ALL_VEHICLES Travel_TIME_PASSENGER_VEHICLES Travel_TIME_FREIGHT_TRUCKS 0 103N04152 2013-09-25 17:35:00 9252013 211 12 12 NaN 1 103N04152 2013-09-26 00:00:00 9262013 0 7 7 NaN 2 103N04152 2013-09-03 14:45:00 9032013 177 8 8 NaN 3 103N04152 2013-09-04 14:30:00 9042013 176 8 9 7 

Ahora, puedo hacer esta fila por fila como mencioné anteriormente haciendo una de estas tres cosas:

 In [3]: df = pd.read_csv('C:/Projects/NPMRDS/FHWA_TASK2-4_NJ_09_2013_TT.CSV', converters={'DATE': lambda x: datetime.datetime.strptime(x, '%m%d%Y'), 'EPOCH': lambda x: str(datetime.timedelta(minutes = int(x)*5))}, parse_dates = {'date_time': ['DATE', 'EPOCH']}, keep_date_col = True) df.head() Out [3]: date_time TMC DATE EPOCH Travel_TIME_ALL_VEHICLES Travel_TIME_PASSENGER_VEHICLES Travel_TIME_FREIGHT_TRUCKS 0 2013-09-25 17:35:00 103N04152 2013-09-25 17:35:00 12 12 NaN 1 2013-09-26 00:00:00 103N04152 2013-09-26 00:00:00 7 7 NaN 2 2013-09-03 14:45:00 103N04152 2013-09-03 14:45:00 8 8 NaN 3 2013-09-04 14:40:00 103N04152 2013-09-04 14:40:00 8 9 7 4 2013-09-05 09:35:00 103N04152 2013-09-05 09:35:00 10 10 NaN 

En este método pierdo el formato original de DATE y EPOCH , pero en realidad no afecta a otros cálculos en el dataframe. En lugar de usar convertidores como argumento, podría haber usado date_parser . O, después de leer los datos, similar a la línea 1, podría haber hecho algo como esto:

 In [4]: df = pd.read_csv('C:/Projects/NPMRDS/FHWA_TASK2-4_NJ_09_2013_TT.CSV') df['date_time'] = pd.to_datetime([datetime.datetime.strptime(str(df['DATE'][x]), '%m%d%Y') + datetime.timedelta(minutes = int(df['EPOCH'][x]*5)) for x in range(len(df))]) df.head() Out [4]: TMC DATE EPOCH Travel_TIME_ALL_VEHICLES Travel_TIME_PASSENGER_VEHICLES Travel_TIME_FREIGHT_TRUCKS DATE_TIME 0 103N04152 9252013 211 12 12 NaN 2013-09-25 17:35:00 1 103N04152 9262013 0 7 7 NaN 2013-09-26 00:00:00 2 103N04152 9032013 177 8 8 NaN 2013-09-03 14:45:00 3 103N04152 9042013 176 8 9 7 2013-09-04 14:40:00 4 103N04152 9052013 115 10 10 NaN 2013-09-05 09:35:00 

Un resultado más deseable (no se preocupe por los pedidos de columnas), pero aún así fila por fila, y toma una enorme cantidad de tiempo.

Luego están pandas.to_datetime y pandas.to_timedelta , que se ejecutan mucho más rápido que los métodos descritos anteriormente. Pero no puedo combinar los resultados sin recurrir a las funciones de cadena, que de nuevo son principalmente fila por fila. ¿Alguien sabe una mejor manera de hacer esto?

Edición: Solución !!!

Además de la respuesta de chrisb , también encontré una forma de hacerlo. El truco está en establecer el parámetro de box en False en pandas.to_datetime() . Al igual que:

 df['DATE_TIME'] = pd.to_datetime(df['DATE'], format='%m%d%Y', box=False) + pd.to_timedelta(df['EPOCH']*5*60, unit='s') 

Si se establece en False devuelve una numpy.datetime[64] , en lugar de pandas.DatetimeIndex . Puede encontrar más información en la documentación de pandas.to_datetime() . Y, pandas.to_timedelta() no funciona con la unit='m' .

Pruebe esto: redujo el tiempo de ejecución a aproximadamente 1 s (en comparación con 15 s) en 4M filas de datos de prueba.

 df = pd.read_csv('temp.csv') df['DATE'] = pd.to_datetime(df['DATE'], format='%m%d%Y') df['EPOCH'] = pd.to_timedelta((df['EPOCH'].astype(int) * 5).astype('timedelta64[m]')) df['DATE_TIME'] = df['DATE'] + df['EPOCH']