Как применить tz_convert с разными часовыми поясами к разным строкам в кадре данных pandas

Я пытаюсь установить разные часовые пояса для разных строк в кадре данных Pandas на основе критерия. Как MWE, вот что я пробовал:

test = pd.DataFrame( data = pd.to_datetime(['2015-03-30 20:12:32','2015-03-12 00:11:11']) ,columns=['time'] )
test['new_col']=['new','old']
test.time=test.set_index('time').index.tz_localize('UTC')
test.loc[test.new_col=='new','time']=test[test.new_col=='new'].set_index('time').index.tz_convert('US/Pacific')
print test

Результат этого:

                        time new_col
0        1427746352000000000     new
1  2015-03-12 00:11:11+00:00     old

Как видите, строка с обновленным часовым поясом преобразуется в целое число. Как я могу сделать это правильно, чтобы обновленная запись была датой и временем?


person Cory Schillaci    schedule 07.10.2015    source источник
comment
Невозможно иметь разные часовые пояса в одном столбце (столбцы имеют однородный тип)   -  person joris    schedule 07.10.2015
comment
Это не похоже на правду, см. пример ниже.   -  person Cory Schillaci    schedule 07.10.2015
comment
Да, но, как объяснил @jreback, у вас больше нет столбца даты и времени, а есть столбцы объектов (которые в принципе могут содержать что угодно), теряя большую часть полезной функциональности.   -  person joris    schedule 08.10.2015


Ответы (2)


Используя 0.17.0rc2 (0.17.0 выпущена 9 октября), вы можете сделать это.

In [43]: test['new_col2'] = [Timestamp('2015-03-30 20:12:32',tz='US/Eastern'),Timestamp('2015-03-30 20:12:32',tz='US/Pacific')]

In [44]: test
Out[44]: 
                       time new_col                   new_col2
0 2015-03-30 20:12:32+00:00     new  2015-03-30 20:12:32-04:00
1 2015-03-12 00:11:11+00:00     old  2015-03-30 20:12:32-07:00

In [45]: test.dtypes
Out[45]: 
time        datetime64[ns, UTC]
new_col                  object
new_col2                 object
dtype: object

Обратите внимание, что смешанные часовые пояса внутри столбца с принудительным object dtype. Так что это можно сделать, но, как правило, не рекомендуется. Вам нужно будет изменить записи по отдельности.

Вы почти всегда используете один столбец dtyped для одного часового пояса.

person Jeff    schedule 07.10.2015
comment
Я пропустил, что Pandas преобразует столбец смешанного часового пояса в dtype object. Однако, когда я устанавливаю время в качестве индекса (например, test[test.new_col=='new'].set_index('time').index), я действительно получаю DatetimeIndex. Но когда я пытаюсь назначить его обратно в исходный столбец, он превращается в тарабарщину. Можете ли вы объяснить, почему я должен ожидать такого поведения? - person Cory Schillaci; 07.10.2015
comment
в 0.16.2 это ошибка, в 0.17.0 это вызовет , см. здесь - person Jeff; 07.10.2015

Вот решение, которое работает, если вы добавите столбец, указывающий часовой пояс для преобразования.

utc_df = pd.DataFrame({"timestamp": [pd.Timestamp("2019-09-01 12:00:00+0000", tz="UTC"),
                                     pd.Timestamp("2019-11-01 12:00:00+0000", tz="UTC")],
                        "timezone": ["Europe/Brussels", "Europe/London"]})

Этот образец по-прежнему имеет время в формате UTC и выглядит так:

                  timestamp         timezone 
0 2019-09-01 12:00:00+00:00  Europe/Brussels 
1 2019-11-01 12:00:00+00:00    Europe/London

Затем мы группируем по часовому поясу и применяем преобразование.

def localize_time(df):
    def convert_tz(tz_df):
        return tz_df.set_index('timestamp').tz_convert(tz_df.timezone.values[0]).reset_index()

    return df.groupby('timezone').apply(convert_tz).reset_index(drop=True)

localize_time(utc_df)

Что возвращает:

                   timestamp         timezone
0  2019-09-01 14:00:00+02:00  Europe/Brussels
1  2019-11-01 12:00:00+00:00    Europe/London

Обратите внимание, столбец dtype временной метки изменится на object.

utc_df.dtypes
timestamp    datetime64[ns, UTC]
timezone                  object

localize_time(utc_df).dtypes
timestamp    object
timezone     object

Однако вы по-прежнему можете получить доступ к функциям даты и времени в этом столбце, пока вы продолжаете группировать по часовому поясу, а затем применяете нужную функцию (как в примере, показанном здесь).

person Jeroen Boeye    schedule 22.11.2019