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