【问题标题】:Python Pandas: Supporting 25 hours in datetime indexPython Pandas:支持 25 小时的日期时间索引
【发布时间】:2020-12-05 22:17:59
【问题描述】:

我想在 Pandas 中使用日期/时间作为数据框的索引。

但是,数据库中没有正确处理夏令时,因此夏令时结束的那一天的日期/时间值有 25 小时,并表示如下:

2019102700
2019102701
...
2019102724

我正在使用以下代码将这些值转换为 DateTime 对象,我将其用作 Pandas 数据框的索引:

df.index = pd.to_datetime(df["date_time"], format="%Y%m%d%H")

但是,这给出了一个错误:

ValueError: unconverted data remains: 4

大概是因为to_datetime 函数不期望小时为24。同样,夏令时开始的日期只有 23 小时。

我想到的一个解决方案是将日期存储为字符串,但这似乎既不优雅也不高效。有没有办法解决使用to_datetime时处理夏令时的问题?

【问题讨论】:

  • 尝试df['date'] = df.index.to_series().str.slice(stop=-2) 和倒数.slice(start=-2) 的时间,然后用日历操作夏令时时间
  • 您知道时区吗?时间间隔是否像您的示例(1h)一样规律?
  • @MrFuppes 是的,我愿意

标签: python-3.x pandas dataframe datetime


【解决方案1】:

如果您知道时区,这里有一种计算 UTC 时间戳的方法。仅解析日期部分,本地化为数据“所属”的实际时区,并将其转换为 UTC。现在您可以解析小时部分并将其添加为时间增量 - 例如

import pandas as pd 

df = pd.DataFrame({'date_time_str': ['2019102722','2019102723','2019102724',
                                     '2019102800','2019102801','2019102802']})

df['date_time'] = (pd.to_datetime(df['date_time_str'].str[:-2], format='%Y%m%d')
                   .dt.tz_localize('Europe/Berlin')
                   .dt.tz_convert('UTC'))

df['date_time'] += df['date_time_str'].str[-2:].astype('timedelta64[h]')

# df['date_time']
# 0   2019-10-27 20:00:00+00:00
# 1   2019-10-27 21:00:00+00:00
# 2   2019-10-27 22:00:00+00:00
# 3   2019-10-27 23:00:00+00:00
# 4   2019-10-28 00:00:00+00:00
# 5   2019-10-28 01:00:00+00:00
# Name: date_time, dtype: datetime64[ns, UTC]

【讨论】:

    【解决方案2】:

    我不确定这是否是最优雅或最有效的解决方案,但我会:

    df.loc[df.date_time.str[-2:]=='25', 'date_time'] = (pd.to_numeric(df.date_time[df.date_time.str[-2:]=='25'])+100-24).apply(str)
    df.index = pd.to_datetime(df["date_time"], format="%Y%m%d%H")
    

    【讨论】:

    • 我更喜欢 MrFuppes 的解决方案,但感谢您的回答,这也有效!名字也不错:)
    【解决方案3】:

    选择第一个和最后一个索引,将它们转换为 tz_aware datetime,然后您可以生成一个处理 25 小时制的 date_range。并将 date_range 分配给您的 df 索引:

    start = pd.to_datetime(df.index[0]).tz_localize("Europe/Berlin")
    end = pd.to_datetime(df.index[-1]).tz_localize("Europe/Berlin")
    index_ = pd.date_range(start, end, freq="15min")
    df = df.set_index(index_)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 2017-01-03
      • 2014-03-07
      • 2015-03-27
      • 2018-10-30
      • 2017-04-16
      相关资源
      最近更新 更多