DST 更改日的 `combine_first` 失败
`combine_first` at DST changing day fails
我正在尝试使用 combine_first
加入两个 pandas 系列,以便一个优先于另一个。但它在 DST 更改日失败。我整理了这个演示:
import pandas as pd
import numpy as np
fr1 = pd.date_range(pd.to_datetime('2020-10-25').tz_localize('Europe/Berlin'), pd.to_datetime('2020-10-26').tz_localize('Europe/Berlin'), freq='H')
fr2 = fr1 + pd.DateOffset(hours=12)
d1 = pd.Series(data=np.random.randint(0,10, len(fr1)), index = fr1)
d2 = pd.Series(data=np.random.randint(0,10, len(fr2)), index = fr2)
d2.combine_first(d1)
输出:
ValueError: cannot reindex from a duplicate axis
这是为什么?这怎么能解决?我当然可以手动对系列进行切片和连接。
如您所见,查看 DateTimeIndex
的第一项,时区 +xxxx
在 DST 更改时发生变化:
>>> date_range = pd.date_range(pd.to_datetime('2020-10-25').tz_localize('Europe/Berlin'), pd.to_datetime('2020-10-26').tz_localize('Europe/Berlin'), freq='H')
>>> date_range[:4]
DatetimeIndex(['2020-10-25 00:00:00+02:00', '2020-10-25 01:00:00+02:00',
'2020-10-25 02:00:00+02:00', '2020-10-25 02:00:00+01:00'],
添加 12 小时后,日期也会更改它们的时区:
DatetimeIndex(['2020-10-25 12:00:00+01:00', '2020-10-25 13:00:00+01:00',
'2020-10-25 14:00:00+01:00', '2020-10-25 14:00:00+01:00'],
dtype='datetime64[ns, Europe/Berlin]', freq=None)
然而,时差不再是 12 小时,而是 11 小时,这是由于时区的变化。这是因为将 DateOffset
添加到 DatetimeIndex
时,您要求“明显”变化 12 小时,如“2 个不同的时钟读数相隔 12 小时”。这意味着 2 个时间戳被映射到 12 小时后出现的相同时间戳。
DateOffset
的一个特点是允许表达非常量增量,即如果您添加 « 1 个月 »,您同样不会向日期添加相同的秒数,具体取决于您选择的月份进来了。
如果您想要在 12 个实际小时内轮班,请使用 Timedelta
:
>>> (date_range[:4] + pd.Timedelta(hours=12))
DatetimeIndex(['2020-10-25 11:00:00+01:00', '2020-10-25 12:00:00+01:00',
'2020-10-25 13:00:00+01:00', '2020-10-25 14:00:00+01:00'],
dtype='datetime64[ns, Europe/Berlin]', freq='H')
>>> (date_range + pd.Timedelta(hours=12)).is_unique
True
既然索引是唯一的,combine_first
也可以工作:
>>> d1 = pd.Series(data=np.random.randint(0, 10, 26), index=date_range)
>>> d2 = pd.Series(data=np.random.randint(0, 10, 26), index=date_range + pd.Timedelta(hours=12))
>>> d2.combine_first(d1)
2020-10-25 00:00:00+02:00 0.0
2020-10-25 01:00:00+02:00 1.0
2020-10-25 02:00:00+02:00 2.0
2020-10-25 02:00:00+01:00 1.0
2020-10-25 03:00:00+01:00 7.0
2020-10-25 04:00:00+01:00 4.0
2020-10-25 05:00:00+01:00 0.0
2020-10-25 06:00:00+01:00 1.0
2020-10-25 07:00:00+01:00 1.0
2020-10-25 08:00:00+01:00 1.0
2020-10-25 09:00:00+01:00 6.0
2020-10-25 10:00:00+01:00 7.0
2020-10-25 11:00:00+01:00 4.0
2020-10-25 12:00:00+01:00 8.0
2020-10-25 13:00:00+01:00 6.0
2020-10-25 14:00:00+01:00 0.0
2020-10-25 15:00:00+01:00 6.0
2020-10-25 16:00:00+01:00 0.0
2020-10-25 17:00:00+01:00 0.0
2020-10-25 18:00:00+01:00 9.0
2020-10-25 19:00:00+01:00 7.0
2020-10-25 20:00:00+01:00 9.0
2020-10-25 21:00:00+01:00 3.0
2020-10-25 22:00:00+01:00 4.0
2020-10-25 23:00:00+01:00 0.0
2020-10-26 00:00:00+01:00 6.0
2020-10-26 01:00:00+01:00 5.0
2020-10-26 02:00:00+01:00 9.0
2020-10-26 03:00:00+01:00 1.0
2020-10-26 04:00:00+01:00 4.0
2020-10-26 05:00:00+01:00 4.0
2020-10-26 06:00:00+01:00 3.0
2020-10-26 07:00:00+01:00 1.0
2020-10-26 08:00:00+01:00 8.0
2020-10-26 09:00:00+01:00 1.0
2020-10-26 10:00:00+01:00 6.0
2020-10-26 11:00:00+01:00 5.0
2020-10-26 12:00:00+01:00 6.0
Freq: H, dtype: float64
我正在尝试使用 combine_first
加入两个 pandas 系列,以便一个优先于另一个。但它在 DST 更改日失败。我整理了这个演示:
import pandas as pd
import numpy as np
fr1 = pd.date_range(pd.to_datetime('2020-10-25').tz_localize('Europe/Berlin'), pd.to_datetime('2020-10-26').tz_localize('Europe/Berlin'), freq='H')
fr2 = fr1 + pd.DateOffset(hours=12)
d1 = pd.Series(data=np.random.randint(0,10, len(fr1)), index = fr1)
d2 = pd.Series(data=np.random.randint(0,10, len(fr2)), index = fr2)
d2.combine_first(d1)
输出:
ValueError: cannot reindex from a duplicate axis
这是为什么?这怎么能解决?我当然可以手动对系列进行切片和连接。
如您所见,查看 DateTimeIndex
的第一项,时区 +xxxx
在 DST 更改时发生变化:
>>> date_range = pd.date_range(pd.to_datetime('2020-10-25').tz_localize('Europe/Berlin'), pd.to_datetime('2020-10-26').tz_localize('Europe/Berlin'), freq='H')
>>> date_range[:4]
DatetimeIndex(['2020-10-25 00:00:00+02:00', '2020-10-25 01:00:00+02:00',
'2020-10-25 02:00:00+02:00', '2020-10-25 02:00:00+01:00'],
添加 12 小时后,日期也会更改它们的时区:
DatetimeIndex(['2020-10-25 12:00:00+01:00', '2020-10-25 13:00:00+01:00',
'2020-10-25 14:00:00+01:00', '2020-10-25 14:00:00+01:00'],
dtype='datetime64[ns, Europe/Berlin]', freq=None)
然而,时差不再是 12 小时,而是 11 小时,这是由于时区的变化。这是因为将 DateOffset
添加到 DatetimeIndex
时,您要求“明显”变化 12 小时,如“2 个不同的时钟读数相隔 12 小时”。这意味着 2 个时间戳被映射到 12 小时后出现的相同时间戳。
DateOffset
的一个特点是允许表达非常量增量,即如果您添加 « 1 个月 »,您同样不会向日期添加相同的秒数,具体取决于您选择的月份进来了。
如果您想要在 12 个实际小时内轮班,请使用 Timedelta
:
>>> (date_range[:4] + pd.Timedelta(hours=12))
DatetimeIndex(['2020-10-25 11:00:00+01:00', '2020-10-25 12:00:00+01:00',
'2020-10-25 13:00:00+01:00', '2020-10-25 14:00:00+01:00'],
dtype='datetime64[ns, Europe/Berlin]', freq='H')
>>> (date_range + pd.Timedelta(hours=12)).is_unique
True
既然索引是唯一的,combine_first
也可以工作:
>>> d1 = pd.Series(data=np.random.randint(0, 10, 26), index=date_range)
>>> d2 = pd.Series(data=np.random.randint(0, 10, 26), index=date_range + pd.Timedelta(hours=12))
>>> d2.combine_first(d1)
2020-10-25 00:00:00+02:00 0.0
2020-10-25 01:00:00+02:00 1.0
2020-10-25 02:00:00+02:00 2.0
2020-10-25 02:00:00+01:00 1.0
2020-10-25 03:00:00+01:00 7.0
2020-10-25 04:00:00+01:00 4.0
2020-10-25 05:00:00+01:00 0.0
2020-10-25 06:00:00+01:00 1.0
2020-10-25 07:00:00+01:00 1.0
2020-10-25 08:00:00+01:00 1.0
2020-10-25 09:00:00+01:00 6.0
2020-10-25 10:00:00+01:00 7.0
2020-10-25 11:00:00+01:00 4.0
2020-10-25 12:00:00+01:00 8.0
2020-10-25 13:00:00+01:00 6.0
2020-10-25 14:00:00+01:00 0.0
2020-10-25 15:00:00+01:00 6.0
2020-10-25 16:00:00+01:00 0.0
2020-10-25 17:00:00+01:00 0.0
2020-10-25 18:00:00+01:00 9.0
2020-10-25 19:00:00+01:00 7.0
2020-10-25 20:00:00+01:00 9.0
2020-10-25 21:00:00+01:00 3.0
2020-10-25 22:00:00+01:00 4.0
2020-10-25 23:00:00+01:00 0.0
2020-10-26 00:00:00+01:00 6.0
2020-10-26 01:00:00+01:00 5.0
2020-10-26 02:00:00+01:00 9.0
2020-10-26 03:00:00+01:00 1.0
2020-10-26 04:00:00+01:00 4.0
2020-10-26 05:00:00+01:00 4.0
2020-10-26 06:00:00+01:00 3.0
2020-10-26 07:00:00+01:00 1.0
2020-10-26 08:00:00+01:00 8.0
2020-10-26 09:00:00+01:00 1.0
2020-10-26 10:00:00+01:00 6.0
2020-10-26 11:00:00+01:00 5.0
2020-10-26 12:00:00+01:00 6.0
Freq: H, dtype: float64