pandas DatetimeIndex.round 的行为不一致?
Inconsistent behavior of pandas DatetimeIndex.round?
我在 pandas.DatetimeIndex 的循环方法中遇到了一个奇怪的、非常出乎意料的行为:
import pandas as pd
import datetime as dt
t1 = pd.DatetimeIndex([dt.datetime(2013,12,5,1,30,0),
dt.datetime(2013,12,5,2,30,0),
dt.datetime(2013,12,5,3,30,0),
dt.datetime(2013,12,5,4,30,0)])
print(t1)
给出:
DatetimeIndex(['2013-12-05 01:30:00', '2013-12-05 02:30:00',
'2013-12-05 03:30:00', '2013-12-05 04:30:00'],
dtype='datetime64[ns]', freq=None)
到目前为止,还不错。现在我想四舍五入到最接近的整点。我不介意选择下一个小时还是前一个小时。但我需要一致的行为。
t2 = t1.round('H')
print(t2)
令人惊讶的是我得到:
DatetimeIndex(['2013-12-05 02:00:00', '2013-12-05 02:00:00',
'2013-12-05 04:00:00', '2013-12-05 04:00:00'],
dtype='datetime64[ns]', freq=None)
条目 1 和 3 向上舍入,而条目 2 和 4 向下舍入。这是应该的行为吗?我猜引擎盖下有一些数字的东西。但这确实令人不安。在我的例子中,时间分辨率被限制在几分钟内。所以我每次都可以加(或减)1s 并得到想要的结果。但这不是正确的做法。
许多人学习 "round half up" 规则,例如 1.5 舍入为 2,2.5 舍入为 3,等等。这是 不是 在 numpy 中处理舍入的方式.来自numpy.around
,强调我自己的。
For values exactly halfway between rounded decimal values, NumPy
rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, -0.5
and 0.5 round to 0.0, etc.
将您的时间视为小时分数,这将是预期的行为:
np.around([1.5, 2.5, 3.5, 4.5])
#array([2., 2., 4., 4.])
(pandas 定义相同的行为,使用 RoundTo.NEAREST_HALF_EVEN
进行舍入)
那么如何用频率四舍五入一个日期时间?
Buried deep 是一种 RoundTo
方法,我们想要的舍入是 RoundTo.NEAREST_HALF_PLUS_INFTY
。我们需要处理 datetimes
的复杂性,但是 pandas 已经处理好了;还导入 round_nsint64
方法。
from pandas._libs.tslibs.timestamps import RoundTo, round_nsint64
# rounded int64s
rounded = round_nsint64(t1.view('i8'), RoundTo.NEAREST_HALF_PLUS_INFTY, 'H')
# Convert back to datetime
pd.DatetimeIndex(rounded)
#DatetimeIndex(['2013-12-05 02:00:00', '2013-12-05 03:00:00',
# '2013-12-05 04:00:00', '2013-12-05 05:00:00'],
# dtype='datetime64[ns]', freq=None)
我在 pandas.DatetimeIndex 的循环方法中遇到了一个奇怪的、非常出乎意料的行为:
import pandas as pd
import datetime as dt
t1 = pd.DatetimeIndex([dt.datetime(2013,12,5,1,30,0),
dt.datetime(2013,12,5,2,30,0),
dt.datetime(2013,12,5,3,30,0),
dt.datetime(2013,12,5,4,30,0)])
print(t1)
给出:
DatetimeIndex(['2013-12-05 01:30:00', '2013-12-05 02:30:00',
'2013-12-05 03:30:00', '2013-12-05 04:30:00'],
dtype='datetime64[ns]', freq=None)
到目前为止,还不错。现在我想四舍五入到最接近的整点。我不介意选择下一个小时还是前一个小时。但我需要一致的行为。
t2 = t1.round('H')
print(t2)
令人惊讶的是我得到:
DatetimeIndex(['2013-12-05 02:00:00', '2013-12-05 02:00:00',
'2013-12-05 04:00:00', '2013-12-05 04:00:00'],
dtype='datetime64[ns]', freq=None)
条目 1 和 3 向上舍入,而条目 2 和 4 向下舍入。这是应该的行为吗?我猜引擎盖下有一些数字的东西。但这确实令人不安。在我的例子中,时间分辨率被限制在几分钟内。所以我每次都可以加(或减)1s 并得到想要的结果。但这不是正确的做法。
许多人学习 "round half up" 规则,例如 1.5 舍入为 2,2.5 舍入为 3,等等。这是 不是 在 numpy 中处理舍入的方式.来自numpy.around
,强调我自己的。
For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, -0.5 and 0.5 round to 0.0, etc.
将您的时间视为小时分数,这将是预期的行为:
np.around([1.5, 2.5, 3.5, 4.5])
#array([2., 2., 4., 4.])
(pandas 定义相同的行为,使用 RoundTo.NEAREST_HALF_EVEN
进行舍入)
那么如何用频率四舍五入一个日期时间?
Buried deep 是一种 RoundTo
方法,我们想要的舍入是 RoundTo.NEAREST_HALF_PLUS_INFTY
。我们需要处理 datetimes
的复杂性,但是 pandas 已经处理好了;还导入 round_nsint64
方法。
from pandas._libs.tslibs.timestamps import RoundTo, round_nsint64
# rounded int64s
rounded = round_nsint64(t1.view('i8'), RoundTo.NEAREST_HALF_PLUS_INFTY, 'H')
# Convert back to datetime
pd.DatetimeIndex(rounded)
#DatetimeIndex(['2013-12-05 02:00:00', '2013-12-05 03:00:00',
# '2013-12-05 04:00:00', '2013-12-05 05:00:00'],
# dtype='datetime64[ns]', freq=None)