python timezone dataframe pandas multi-index

python - Cambiar la zona horaria de la columna de fecha y hora en pandas y agregar como índice jerárquico



timezone dataframe (4)

Tengo datos con una marca de tiempo en UTC. Me gustaría convertir la zona horaria de esta marca de tiempo en ''US / Pacific'' y agregarla como un índice jerárquico a un DataFrame de pandas. Pude convertir la marca de tiempo como un índice, pero pierde el formato de zona horaria cuando intento volver a agregarlo al marco de datos, ya sea como una columna o como un índice.

>>> import pandas as pd >>> dat = pd.DataFrame({''label'':[''a'', ''a'', ''a'', ''b'', ''b'', ''b''], ''datetime'':[''2011-07-19 07:00:00'', ''2011-07-19 08:00:00'', ''2011-07-19 09:00:00'', ''2011-07-19 07:00:00'', ''2011-07-19 08:00:00'', ''2011-07-19 09:00:00''], ''value'':range(6)}) >>> dat.dtypes #datetime object #label object #value int64 #dtype: object

Ahora, si trato de convertir la serie directamente, me encuentro con un error.

>>> times = pd.to_datetime(dat[''datetime'']) >>> times.tz_localize(''UTC'') #Traceback (most recent call last): # File "<stdin>", line 1, in <module> # File "/Users/erikshilts/workspace/schedule-detection/python/pysched/env/lib/python2.7/site-packages/pandas/core/series.py", line 3170, in tz_localize # raise Exception(''Cannot tz-localize non-time series'') #Exception: Cannot tz-localize non-time series

Si lo convierto en un índice, entonces puedo manipularlo como una serie temporal. Tenga en cuenta que el índice ahora tiene la zona horaria del Pacífico.

>>> times_index = pd.Index(times) >>> times_index_pacific = times_index.tz_localize(''UTC'').tz_convert(''US/Pacific'') >>> times_index_pacific #<class ''pandas.tseries.index.DatetimeIndex''> #[2011-07-19 00:00:00, ..., 2011-07-19 02:00:00] #Length: 6, Freq: None, Timezone: US/Pacific

Sin embargo, ahora me encuentro con problemas para volver a agregar el índice al marco de datos a medida que pierde su formato de zona horaria:

>>> dat_index = dat.set_index([dat[''label''], times_index_pacific]) >>> dat_index # datetime label value #label #a 2011-07-19 07:00:00 2011-07-19 07:00:00 a 0 # 2011-07-19 08:00:00 2011-07-19 08:00:00 a 1 # 2011-07-19 09:00:00 2011-07-19 09:00:00 a 2 #b 2011-07-19 07:00:00 2011-07-19 07:00:00 b 3 # 2011-07-19 08:00:00 2011-07-19 08:00:00 b 4 # 2011-07-19 09:00:00 2011-07-19 09:00:00 b 5

Notará que el índice está de regreso en la zona horaria UTC en lugar de la zona horaria convertida de Pacific.

¿Cómo puedo cambiar la zona horaria y agregarla como un índice a un DataFrame?


La solución alternativa no parece funcionar porque los niveles de índice de un índice jerárquico parecen ser inmutables (FrozenList es inmutable).

Comenzar con un índice singular y anexar tampoco funciona.

Crear una función lambda que arroje como Timestamp y convierta cada miembro de la serie devuelto por to_datetime () tampoco funciona.

¿Hay alguna manera de crear Series con reconocimiento de zona horaria y luego insertarlas en un marco de datos / hacer que sean un índice?

joined_event_df = joined_event_df.set_index([''pandasTime'']) joined_event_df.index = joined_event_df.index.get_level_values(1).tz_localize(''UTC'').tz_convert(''US/Central'') # we have tz-awareness above this line joined_event_df = joined_event_df.set_index(''sequence'', append = True) # we lose tz-awareness in the index as soon as we add another index joined_event_df = joined_event_df.swaplevel(0,1)


Otra solución que funciona en pandas 0.13.1 y resuelve el problema de FrozenList no se puede asignar:

index.levels = pandas.core.base.FrozenList([ index.levels[0].tz_localize(''UTC'').tz_convert(tz), index.levels[1].tz_localize(''UTC'').tz_convert(tz) ])

Luchando mucho con este problema, MultiIndex pierde tz en muchas otras condiciones también.


Por ahora esto ha sido arreglado. Por ejemplo, ahora puede llamar:

dataframe.tz_localize(''UTC'', level=0)

Sin embargo, tendrá que llamarlo dos veces para el ejemplo dado. (Es decir, una vez para cada nivel)


Si lo configura como el índice, se convierte automáticamente en un índice:

In [11]: dat.index = pd.to_datetime(dat.pop(''datetime''), utc=True) In [12]: dat Out[12]: label value datetime 2011-07-19 07:00:00 a 0 2011-07-19 08:00:00 a 1 2011-07-19 09:00:00 a 2 2011-07-19 07:00:00 b 3 2011-07-19 08:00:00 b 4 2011-07-19 09:00:00 b 5

Luego haz el tz_localize :

In [12]: dat.index = dat.index.tz_localize(''UTC'').tz_convert(''US/Pacific'') In [13]: dat Out[13]: label value datetime 2011-07-19 00:00:00-07:00 a 0 2011-07-19 01:00:00-07:00 a 1 2011-07-19 02:00:00-07:00 a 2 2011-07-19 00:00:00-07:00 b 3 2011-07-19 01:00:00-07:00 b 4 2011-07-19 02:00:00-07:00 b 5

Y luego puede agregar la columna de etiqueta al índice:

Hmmm, este es definitivamente un error!

In [14]: dat.set_index(''label'', append=True).swaplevel(0, 1) Out[14]: value label datetime a 2011-07-19 07:00:00 0 2011-07-19 08:00:00 1 2011-07-19 09:00:00 2 b 2011-07-19 07:00:00 3 2011-07-19 08:00:00 4 2011-07-19 09:00:00 5

Una solución alternativa es convertir el nivel (datetime) directamente (cuando ya es un MultiIndex):

In [15]: dat.index.levels[1] = dat.index.get_level_values(1).tz_localize(''UTC'').tz_convert(''US/Pacific'') In [16]: dat1 Out[16]: value label datetime a 2011-07-19 00:00:00-07:00 0 2011-07-19 01:00:00-07:00 1 2011-07-19 02:00:00-07:00 2 b 2011-07-19 00:00:00-07:00 3 2011-07-19 01:00:00-07:00 4 2011-07-19 02:00:00-07:00 5