【问题标题】:How to trucnate/round to hour a localized datetime column in pandas如何在熊猫中截断/舍入到小时的本地化日期时间列
【发布时间】:2018-03-06 13:33:18
【问题描述】:

我想在 pandas python 中截断/舍入到小时的本地化日期时间列。例如,如果我有 2017-10-15 15:03:25+02:00 我想获得 2017-10-15 15:00:00+02:00。请注意,我想保留时区信息。 我尝试的第一件事是:

DF['dtColumn'].dt.floor('H')

这显然可以截断到小时并保留时区信息,问题出现在 dst 日到来时,例如 2017 年 10 月 29 日。给定以下代码:

dt1 = datetime.datetime(2017,10,29,0,1)
dt2 = datetime.datetime(2017,10,29,1,1)
df = pd.DataFrame([('whatever', dt1),('whatever',dt2)])
df[1] = df[1].dt.tz_localize('UTC').dt.tz_convert('Europe/Madrid')
df[1].dt.floor('H')

它产生给定的错误:

    Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\IPython\core\interactiveshell.py", line 2882, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-90-8319339cf020>", line 5, in <module>
    df[1].dt.floor('H')
  File "C:\Python27\lib\site-packages\pandas\core\base.py", line 210, in f
    return self._delegate_method(name, *args, **kwargs)
  File "C:\Python27\lib\site-packages\pandas\tseries\common.py", line 132, in _delegate_method
    result = method(*args, **kwargs)
  File "C:\Python27\lib\site-packages\pandas\tseries\base.py", line 101, in floor
    return self._round(freq, np.floor)
  File "C:\Python27\lib\site-packages\pandas\tseries\base.py", line 93, in _round
    self._shallow_copy(result, **attribs))
  File "C:\Python27\lib\site-packages\pandas\tseries\base.py", line 213, in _ensure_localized
    result = result.tz_localize(self.tz)
  File "C:\Python27\lib\site-packages\pandas\util\decorators.py", line 91, in wrapper
    return func(*args, **kwargs)
  File "C:\Python27\lib\site-packages\pandas\tseries\index.py", line 1826, in tz_localize
    errors=errors)
  File "pandas\tslib.pyx", line 4380, in pandas.tslib.tz_localize_to_utc (pandas\tslib.c:75768)
AmbiguousTimeError: Cannot infer dst time from Timestamp('2017-10-29 02:00:00'), try using the 'ambiguous' argument

错误提示使用“歧义”参数,如果出现歧义,则需要做出预定义的决定。但是在我的数据框中,我不会说有这样的歧义,因为我有时区信息,并且在四舍五入后我仍然想要它。我宁愿避免歧义。

我也找到了解决办法:

df.loc[:, 1].values.astype('<M8[h]')

这通常适用于复杂的时区。例如尼泊尔的时区(亚洲/加德满都)是 GMT+5:45。同样,我想做的是将日期时间在本地时区截断到小时,在尝试上面的代码后,我观察到这会将其转换为 utc,然后截断,所以当它返回时本地化的日期时间我没有将它分组在确切的小时内,而是按每个 :45 分组。

代码:

dt1 = datetime.datetime(2017, 10, 29, 0, 1)
dt2 = datetime.datetime(2017, 10, 29, 1, 1)
df = pd.DataFrame([('whatever', dt1), ('whatever', dt2)])
df[1] = df[1].dt.tz_localize('Asia/Katmandu')
df[2] = df.loc[:, 1].values.astype('<M8[h]')
df[2].dt.tz_localize('UTC').dt.tz_convert('Asia/Katmandu')

我们得到以下结果:

0   2017-10-28 23:45:00+05:45
1   2017-10-29 00:45:00+05:45
Name: 2, dtype: datetime64[ns, Asia/Katmandu]

这证明我的问题的答案不是将日期时间转换为 'utc' 或时间戳,而是将它们整理并转换回本地化。

python datetime 的本机库有一个方法 replace,其中可以将分钟和秒信息替换为 0,但我在 pandas 中没有找到类似的日期时间列。我想找到一个不同的解决方案来逐行迭代,因为我的数据框很大。 关于如何根据此约束将 pandas 中的日期时间列截断为小时的任何想法?

【问题讨论】:

    标签: python pandas datetime timezone truncate


    【解决方案1】:

    我观察到这会将其转换为 utc,然后截断

    为了大家的利益,我在将日期截断为特定格式时遇到了同样的问题。 astype 函数将日期转换为 UTC,这就是为什么如果您尝试截断之前转换为另一个时区的日期,它不起作用。

    最有效且运行速度也很快的解决方案是使用to_period 函数,如下所示:

    # Comverting string column to datetime with UTC by default
    df['column_name'] = pd.to_datetime(df['column_name'], infer_datetime_format=True, utc=True)
    # Converting to an specific time zone
    df['column_name'] = df['column_name'].dt.tz_convert('Europ
    e/Amsterdam')
    # Removing time offset if needed
    df['column_name'] = df['column_name'].dt.tz_localize(None)
    # Truncating the datetime
    df['column_name'] = df['column_name'].dt.to_period('M').dt.to_timestamp()
    

    如果您想使用其他句号,请查看以下网址:https://pandas.pydata.org/docs/user_guide/timeseries.html#timeseries-offset-aliases

    【讨论】:

      猜你喜欢
      • 2014-08-29
      • 2020-01-05
      • 2019-02-11
      • 2020-02-07
      • 2022-06-13
      • 2022-10-12
      • 2014-01-01
      • 2017-06-16
      • 2018-06-17
      相关资源
      最近更新 更多