Tengo un marco de datos que tiene un índice que reconoce la zona horaria, y cuando trato de insertar una nueva fila en este marco de datos, no funciona, sino que cambia el tipo de índice a 'object' (es decir, no puede agregar en la fila en el tipo actual).
MRE a continuación:
import pandas as pd df = pd.DataFrame({"time": ["2021/06/06 12:00:00"], "col1": [2]}) df.index = pd.to_datetime(df['time']) df = df.drop('time', axis=1) df.index = df.index.tz_localize('UTC') # Doesn't work, index is now 'object' as this is considered a string # row = pd.Series(name='2021/06/05 12:00:00') # df = df.append(row) # Also doesn't work, as timezones differ row = pd.Series(name=pd.Timestamp('2021/06/05 12:00:00')) df = df.append(row) print(df.index)Entiendo que puedo hacer lo siguiente:
tz = df.index[0].tz row = pd.Series(name=pd.Timestamp('2021/06/05 12:00:00', tz=tz)) Sin embargo, soy escéptico sobre si esto funcionaría cuando las unidades difieren, o tal vez incluso alguna otra propiedad de una Timestamp de tiempo de pandas que no conozco, por lo que idealmente me gustaría copiar completamente la configuración de la Timestamp de tiempo del índice a la nueva marca de tiempo estoy insertando.
Si alguien supiera cómo insertar una nueva fila en este marco de datos manteniendo intacto el tipo de índice, sería muy apreciado.
Dado que DatetimeTZ solo admite una sola zona horaria, la clave es asegurarse de que la nueva Timestamp de tiempo siempre coincida con su df.index.tz existente.
Al insertar una nueva Timestamp de tiempo:
tz=df.index.tz si es de la misma zona horariaastimezone(df.index.tz) si es de una zona horaria diferente Dado su MRE df :
df # col1 # time # 2021-06-06 12:00:00+00:00 2 df.index.dtype # datetime64[ns, UTC] Si sabe que su nueva Timestamp de tiempo está en el mismo tz , simplemente configúrelo en el constructor como mencionó:
ts1 = pd.Timestamp('2021/06/05 12:00:00', tz=df.index.tz) df.loc[ts1] = 4 # col1 # time # 2021-06-06 12:00:00+00:00 2 # 2021-06-05 12:00:00+00:00 4 df.index.dtype # datetime64[ns, UTC] Si su nueva Timestamp de tiempo está en un tz diferente (que era su principal preocupación), conviértalo usando astimezone (por ejemplo, del este de EE. UU. a UTC):
ts2 = pd.Timestamp('2021/06/05 12:00:00', tz='US/Eastern').astimezone(df.index.tz) df.loc[ts2] = 6 # col1 # time # 2021-06-06 12:00:00+00:00 2 # 2021-06-05 12:00:00+00:00 4 # 2021-06-05 16:00:00+00:00 6 df.index.dtype # datetime64[ns, UTC] Tenga en cuenta que estoy usando loc porque es más rápido y más simple, pero append aún funciona:
ts3 = pd.Timestamp('2021/06/05 12:00:00', tz='US/Central').astimezone(df.index.tz) row = pd.Series([8], name=ts3, index=['col1']) df = df.append(row) # col1 # time # 2021-06-06 12:00:00+00:00 2 # 2021-06-05 12:00:00+00:00 4 # 2021-06-05 16:00:00+00:00 6 # 2021-06-05 17:00:00+00:00 8 df.index.dtype # datetime64[ns, UTC]Los objetos de Timestamp de tiempo son ciertamente del tipo 'object' , y es posible que no pueda escapar del índice para tomar este tipo si usa Timestamp de tiempo como índice.
Por "configuración de marca de tiempo" entiendo "zona horaria", y que desea insertar nuevos tiempos en la misma zona horaria.
O conoce la zona horaria desde el principio y los datos de todas las filas provienen de una fuente que se sabe que es de la misma zona horaria. En ese caso, puede especificar la misma zona horaria cuando crea una instancia de las Timestamp de tiempo.
O no conoce la zona horaria de los datos en primer lugar, y tiene nuevos datos provenientes de otra fuente, por lo que potencialmente de una zona horaria diferente, que ciertamente conoce. Mezclar marcas de tiempo de diferentes zonas horarias no es un problema, ya que las zonas horarias deben tenerse en cuenta al compararlas entre sí. Todavía puede localizarlos todos más tarde en la zona horaria que prefiera.
También podrías hacer algo como esto. DateTimeIndexes son objetos.
for time_zone in ['MST', 'EST', 'GMT']: row = pd.Timestamp('2021/06/05 12:00:00', tz=time_zone) df.loc[row] = 1 # to whichever timezone you want df.index = pd.to_datetime(df.index, utc=True).tz_convert('EST')