получение часа от даты и времени панд, совместимых с изменениями летнего времени - PullRequest
0 голосов
/ 16 мая 2019

У меня есть алгоритм, который принимает в качестве входных данных время в секундах (эпоху) и значение. Он должен сравнивать значение сегодняшнего дня со значениями предыдущих дней в то же время.

Например: сравните сегодня в 5:04 и вчера в 5:04 и так далее.

Переход на летнее время не должен нарушать эту логику. Для достижения желаемого результата я конвертирую эпоху в объект datetime.datetime, а затем подсчитываю количество секунд с полуночи. dt-dt.replace(hour=0, minute=0, second=0, microsecond=0)

Кажется, это хорошо работает с использованием класса python datetime.datetime. К сожалению, это нарушается при преобразовании в панду datetime. Панды, кажется, справляются со сменой часов, меняя часовой пояс.

В этом примере показана разница между пандами datetime и datetime.datetime:

import pandas as pd
import datetime
import pytz

timezone = pytz.timezone('Europe/Rome')


dt_rome = timezone.localize(datetime.datetime(2018, 10, 28, 13, 0, 0))
dts_rome = [dt_rome - datetime.timedelta(hours=24),
            dt_rome,
            dt_rome + datetime.timedelta(hours=24)]

pd_dts_rome = pd.Series(pd.to_datetime(dts_rome))

print 'hour according to python datetime', [dt.hour for dt in dts_rome]
print 'hour according to pandas datetime', [dt.hour for dt in pd_dts_rome]


print 'secs in period python datetime:', [dt-dt.replace(hour=0, minute=0, second=0, microsecond=0)
                                          for dt in dts_rome ]
print 'secs in period pandas datetime:'
print pd_dts_rome.apply(lambda dt: dt-dt.replace(hour=0, minute=0,
                                                 second=0, microsecond=0)).astype(int)/1.e9

выход:

hour according to python datetime [13, 13, 13]
hour according to pandas datetime [14, 13, 13]

secs in period python datetime: [datetime.timedelta(0, 46800), datetime.timedelta(0, 46800), datetime.timedelta(0, 46800)]

secs in period pandas datetime:
0    50400.0
1    50400.0
2    46800.0
dtype: float64

с учетом того, что данные хранятся в кадре данных pandas. Как я могу получить те же результаты, что и с datetime.datetime с pandas.datetime?

1 Ответ

0 голосов
/ 16 мая 2019

Времена, которые вы видите, действительно эквивалентны, но странным образом. Время Панд:

0   2018-10-27 14:00:00+02:00
1   2018-10-28 13:00:00+01:00
2   2018-10-29 13:00:00+01:00
dtype: datetime64[ns, Europe/Rome]

2018-10-28 03:00:00 было, когда летнее время закончилось в Риме. Pandas Series имеет только один логический часовой пояс, который применяется ко всем значениям - это сделано для экономии места и повышения производительности. Итак, ваш часовой пояс - Европа / Рим. Конечно, 14: 00: 00 + 02: 00 - это то же самое физическое время, что и 13: 00: 00 + 01: 00.

времена Python:

datetime.datetime(2018, 10, 27, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)
datetime.datetime(2018, 10, 28, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)
datetime.datetime(2018, 10, 29, 13, 0, tzinfo=<DstTzInfo 'Europe/Rome' CET+1:00:00 STD>)

Первый отличается тем, что Python использует неправильное временное смещение, то есть на самом деле это не Европа / Рим, потому что Рим в то время не был на CET. Это довольно странно и, возможно, менее правильно, чем то, что произвела Панда, поэтому немного неловко спрашивать: «Как заставить Панд делать то же [неправильное], что и Python?»

Но если вам нужно, вы можете:

timezone = pytz.FixedOffset(1)

Остальная часть кода остается прежней. Это говорит: «Смещение моего часового пояса всегда +1 час». Тогда Панды не заметят, когда DST включается и выключается:

0   2018-10-27 13:00:00+00:01
1   2018-10-28 13:00:00+00:01
2   2018-10-29 13:00:00+00:01
dtype: datetime64[ns, pytz.FixedOffset(1)]

Пользователи Python 3 могут вместо этого использовать встроенный datetime.timezone(1), но поскольку вы работаете на Python 2, pytz.FixedOffset(1) выполняет свою работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...