【问题标题】:Pandas convert UNIX time to multiple different timezones depending on column valuePandas 根据列值将 UNIX 时间转换为多个不同的时区
【发布时间】:2021-02-22 13:36:41
【问题描述】:

我有一个带有 UNIX 时间戳的 pandas 数据框(这些是整数,而不是时间对象)。观测发生在多个地理位置,因此发生在多个时区。 我想根据观测的地理位置将 UNIX 时间戳转换为每个时区的本地时间(在新列中)(此信息位于数据框的列中)。

简单的工作示例:

创建数据框:

c1=[1546555701, 1546378818, 1546574677, 1546399159, 1546572278]
c2=['America/Detroit','America/Chicago','America/Los_Angeles','America/Los_Angeles','America/Detroit']

df3=pd.DataFrame(list(zip(c1,c2)),columns=['utc','tz'])

print(df3)

预期输出:

          utc                   tz
0  1546555701      America/Detroit
1  1546378818      America/Chicago
2  1546574677  America/Los_Angeles
3  1546399159  America/Los_Angeles
4  1546572278      America/Detroit

当前尝试:

df3['date_time']=pd.to_datetime(df3['utc'],unit='s')
print(df3)

返回:

          utc                   tz           date_time
0  1546555701      America/Detroit 2019-01-03 22:48:21
1  1546378818      America/Chicago 2019-01-01 21:40:18
2  1546574677  America/Los_Angeles 2019-01-04 04:04:37
3  1546399159  America/Los_Angeles 2019-01-02 03:19:19
4  1546572278      America/Detroit 2019-01-04 03:24:38

这将转换为一个日期时间对象,但我不确定如何控制时区(我认为它给了我本地时区的时间)。它当然不是基于“tz”列。

我查看了 pandas 的 tz_convert() 函数和 arrow package,但无法弄清楚如何使这些工作。我也对其他解决方案持开放态度。 我不仅关心时区,还确保正确处理夏令时。

【问题讨论】:

  • 这些不是 UTC 时间戳。它们可能是 Unix 时间戳。这不是吹毛求疵。在 Unix 系统之外编程时间戳通常意味着完整的 ISO8601 时间戳。在数据库中,timestamp 类型或其等价物是日期+时间值
  • @PanagiotisKanavos 你是对的,我已经相应地改变了问题。
  • 如果您只需要使用这些时间戳工作,我建议将其保留为 UTC 并保留时区信息。如果您需要它用于演示或其他东西(需要它是人类可读的),我只会转换为特定的 tz。
  • @MrFuppes 我需要能够将底特律早上 5:00 的观察结果与波士顿早上 5:00 的观察结果进行比较。这似乎需要这种转换,不是吗?我(可能很明显)是使用时间戳的新手,所以我愿意接受建议和改进的工作流程。
  • 我做了另一个编辑;混合时区很好,但您不能使用 dt 访问器,因此提取单个时间戳属性有点困难。

标签: python pandas datetime timezone dst


【解决方案1】:

假设 POSIX 时间戳(自 1970-01-01 UTC 以来的秒数),您可以使用关键字 utc=True 直接转换为 UTC。

import pandas as pd

c1=[1546555701, 1546378818, 1546574677, 1546399159, 1546572278]
c2=['America/Detroit','America/Chicago','America/Los_Angeles','America/Los_Angeles','America/Detroit']

df3=pd.DataFrame(list(zip(c1,c2)),columns=['utc','tz'])
df3['date_time']=pd.to_datetime(df3['utc'], unit='s', utc=True)

# df3['date_time']
# 0   2019-01-03 22:48:21+00:00
# 1   2019-01-01 21:40:18+00:00
# 2   2019-01-04 04:04:37+00:00
# 3   2019-01-02 03:19:19+00:00
# 4   2019-01-04 03:24:38+00:00
# Name: date_time, dtype: datetime64[ns, UTC]

然后您可以使用 apply 将时区应用于每个值,例如

def setTZ(row):
    return row['date_time'].tz_convert(row['tz'])

df3['date_time']=df3.apply(lambda r: setTZ(r), axis=1)

# df3
#           utc                   tz                  date_time
# 0  1546555701      America/Detroit  2019-01-03 17:48:21-05:00
# 1  1546378818      America/Chicago  2019-01-01 15:40:18-06:00
# 2  1546574677  America/Los_Angeles  2019-01-03 20:04:37-08:00
# 3  1546399159  America/Los_Angeles  2019-01-01 19:19:19-08:00
# 4  1546572278      America/Detroit  2019-01-03 22:24:38-05:00

请注意,对于混合时区,您不能对系列使用 dt 访问器。您需要迭代代码,例如

df3['date_time'].apply(lambda t: t.hour)

获取每个日期时间的小时。解决此问题的一种方法是创建一个具有本地时间但不知道时区的列:

def toLocalTime(row):
    return row['date_time'].tz_convert(row['tz']).replace(tzinfo=None)

df3['local_time'] = df3.apply(lambda r: toLocalTime(r), axis=1)

【讨论】:

  • 我认为 tz_convert() 也处理夏令时,对吗?
  • @amquack:是的。你是对的,对于你提到的比较,只是转换为时区似乎更容易。由于您有 IANA 时区名称,因此这不会造成任何麻烦。但是,由于您有混合时区,dt 访问器将不起作用 - 这可能会有点麻烦,因为您需要交互代码。
  • 我想知道是否有办法做到这一点,而无需逐行进行。您提到了 dt 访问器(我不确定那是什么)。但我想知道这是否是一个有用的工具,可以在转换之前通过按时区排序来加快速度。我问是因为这已经成为我过程中的瓶颈。最初的“to_datetime()函数非常快,但是时区转换很慢(我想是因为它是逐行的)
  • @amquack:我不知道的混合时区。这也是我建议将其保留为 UTC 的原因,因为那部分很快。
猜你喜欢
  • 2020-06-06
  • 2018-04-12
  • 1970-01-01
  • 2019-10-08
  • 2013-05-20
  • 2018-02-08
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多