Группировка по часам с учетом летнего времени - PullRequest
0 голосов
/ 28 декабря 2018

Я смотрю данные смены завода, который работает 24 часа в сутки.Я хочу сгруппировать данные при каждой смене, которая происходит в 6:00 и 18:00.До сих пор я пытался это сделать с помощью:

Data_Frame.groupby([pd.Grouper(freq='12H')]).count() 

Однако я понял, что, поскольку частота установлена ​​на 12H, это всегда будет занимать 12 часов, в том числе при переходе на летнее время.

К сожалению, это всегда 6:00 и 18:00, даже когда часы меняются.Это означает, что на самом деле в году есть одна смена, которая длится 11 часов, а другая - 13 часов, поэтому в середине года группа отключается на 1 час.

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

Я пытался изменить его с UTC на Европу / Лондон, однако это все еще занимает 12 часов.

Большое спасибо

edit:

Единственный способ, которым я нашел это, перед использованием groupby - разделить мои данные на 3 (до изменения первого часа, в течение часаизменение, изменение второго часа) используйте groupby для каждого индивидуально, затем соединяйте их вместе, но это раздражает и утомительно, так что все, что лучше, чем это, очень ценится.

1 Ответ

0 голосов
/ 05 января 2019

Почасовой и 10 минут временной ряд с учетом часового пояса, охватывающий пружина изменение dst:

ts_hrly = pd.date_range('03-10-2018', '3-13-2018', freq='H', tz='US/Eastern')
ts_10m = pd.date_range('03-10-2018', '3-13-2018', freq='10T', tz='US/Eastern')

Использование почасовых данных

ts = ts_hrly
df = pd.DataFrame({'tstamp':ts,'period':range(len(ts))})

Переход dst выглядит следующим образом:

>>> df[18:23]
    period                    tstamp
18      18 2018-03-11 00:00:00-05:00
19      19 2018-03-11 01:00:00-05:00
20      20 2018-03-11 03:00:00-04:00
21      21 2018-03-11 04:00:00-04:00
22      22 2018-03-11 05:00:00-04:00
>>>

Чтобы сгруппировать по двенадцати часовым приращениям на границах 06:00 и 18:00, я назначил каждое наблюдение по номеру смены, затем сгруппировал по номеру смены

Мои данные удобно начинать со смены смены, поэтому рассчитайте время, прошедшее с момента этой первой смены:

nanosec = df['tstamp'].values - df.iloc[0,1].value

Найдите изменения смены и используйте np.cumsum() для назначения номеров смен

shift_change = nanosec.astype(np.int64) % (3600 * 1e9 * 12)  == 0
df['shift_nbr'] = shift_change.cumsum()
gb = df.groupby(df['shift_nbr'])
for k,g in gb:
    print(f'{k} has {len(g)} items')

>>>
1 has 12 items
2 has 12 items
3 has 12 items
4 has 12 items
5 has 12 items
6 has 12 items

Я не нашел способа компенсировать данные, начинающиеся в середине смены.

Если вы хотите, чтобы группы для смен, затронутых изменениями dst, имели 11 или 13 элементов, измените серию с указанием часового пояса на наивную серию часового пояса

df2 = pd.DataFrame({'tstamp':pd.to_datetime(ts.strftime('%m-%d-%y %H:%M')),'period':range(len(ts))})

Используйте тот же процесс, чтобы назначить игруппировка по номерам смены

nanosec = df2['tstamp'].values - df2.iloc[0,1].value
shift_change = nanosec.astype(np.int64) % (3600 * 1e9 * 12)  == 0
df2['shift_nbr'] = shift_change.cumsum()

for k,g in gb2:
    print(f'{k} has {len(g)} items')

>>>
1 has 12 items
2 has 11 items
3 has 12 items
4 has 12 items
5 has 12 items
6 has 12 items
7 has 1 items

К сожалению, pd.to_datetime(ts.strftime('%m-%d-%y %H:%M')) занимает некоторое время.Вот более быстрый / лучший способ сделать это, используя атрибут часа меток времени для расчета прошедших часов - нет необходимости создавать отдельный наивный ряд часовых поясов, атрибут часа выглядит как незнающий .Это также работает для данных, начинающихся в середине смены.

ts = pd.date_range('01-01-2018 03:00', '01-01-2019 06:00', freq='H', tz='US/Eastern')
df3 = pd.DataFrame({'tstamp':ts,'period':range(len(ts))})

shift_change = ((df3['tstamp'].dt.hour - 6) % 12) == 0
shift_nbr = shift_change.cumsum()

gb3 = df3.groupby(shift_nbr)

print(sep,'gb3')
for k,g in gb3:
    if len(g) != 12:
        print(f'shift starting {g.iloc[0,1]} has {len(g)} items')

>>>
shift starting 2018-01-01 03:00:00-05:00 has 3 items
shift starting 2018-03-10 18:00:00-05:00 has 11 items
shift starting 2018-11-03 18:00:00-04:00 has 13 items
shift starting 2019-01-01 06:00:00-05:00 has 1 items
...