按小时分组,同时考虑夏令时
Group by hour whilst taking account of daylight savings
我在看一家24小时不间断工作的工厂的班次数据。我想在每次换班时对数据进行分组,即 6:00 和 18:00。到目前为止,我一直在尝试:
Data_Frame.groupby([pd.Grouper(freq='12H')]).count()
但是我意识到,由于 freq 设置为 12H,所以它总是需要 12 小时,包括夏令时。
不幸的是,它总是 6:00 和 18:00,即使时钟发生变化也是如此。这意味着实际上一年中有一个轮班时间为 11 小时,另一个轮班时间为 13 小时,因此在年中组会关闭 1 小时。
我觉得这是一个非常基本的事情(夏令时),应该有某种方式告诉 pandas 它需要考虑夏令时。
我已经尝试将它从 UTC 更改为 Europe/London,但它仍然需要 12 个小时。
非常感谢
编辑:
我发现这样做的唯一方法是,在使用 groupby 之前将我的数据分成 3 个(在第一个小时更改之前,在更改时间,第二个小时更改之前)分别对每个使用 groupby 然后将它们放回一起但是这既烦人又乏味,因此非常感谢比这更好的东西。
每小时和 10 分钟 时区感知时间序列跨越 spring 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'))
需要一些时间。这是一个 faster/better 使用时间戳的 hour 属性计算经过时间的方法 - 无需创建单独的时区天真系列,hour 属性似乎 unaware.它也适用于从班次中间开始的数据。
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
我在看一家24小时不间断工作的工厂的班次数据。我想在每次换班时对数据进行分组,即 6:00 和 18:00。到目前为止,我一直在尝试:
Data_Frame.groupby([pd.Grouper(freq='12H')]).count()
但是我意识到,由于 freq 设置为 12H,所以它总是需要 12 小时,包括夏令时。
不幸的是,它总是 6:00 和 18:00,即使时钟发生变化也是如此。这意味着实际上一年中有一个轮班时间为 11 小时,另一个轮班时间为 13 小时,因此在年中组会关闭 1 小时。
我觉得这是一个非常基本的事情(夏令时),应该有某种方式告诉 pandas 它需要考虑夏令时。
我已经尝试将它从 UTC 更改为 Europe/London,但它仍然需要 12 个小时。
非常感谢
编辑:
我发现这样做的唯一方法是,在使用 groupby 之前将我的数据分成 3 个(在第一个小时更改之前,在更改时间,第二个小时更改之前)分别对每个使用 groupby 然后将它们放回一起但是这既烦人又乏味,因此非常感谢比这更好的东西。
每小时和 10 分钟 时区感知时间序列跨越 spring 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'))
需要一些时间。这是一个 faster/better 使用时间戳的 hour 属性计算经过时间的方法 - 无需创建单独的时区天真系列,hour 属性似乎 unaware.它也适用于从班次中间开始的数据。
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