如何在熊猫中使用 read_csv 将时区感知日期时间作为时区天真的本地 DatetimeIndex 读取?

Posted

技术标签:

【中文标题】如何在熊猫中使用 read_csv 将时区感知日期时间作为时区天真的本地 DatetimeIndex 读取?【英文标题】:How to read timezone aware datetimes as a timezone naive local DatetimeIndex with read_csv in pandas? 【发布时间】:2016-11-26 15:28:45 【问题描述】:

当我使用 pandas read_csv 读取具有时区感知日期时间的列(并将此列指定为索引)时,pandas 将其转换为 timezone naive utc DatetimeIndex。

Test.csv 中的数据:

DateTime,Temperature 2016-07-01T11:05:07+02:00,21.125 2016-07-01T11:05:09+02:00,21.138 2016-07-01T11:05:10+02:00,21.156 2016-07-01T11:05:11+02:00,21.179 2016-07-01T11:05:12+02:00,21.198 2016-07-01T11:05:13+02:00,21.206 2016-07-01T11:05:14+02:00,21.225 2016-07-01T11:05:15+02:00,21.233

从 csv 读取的代码:

In [1]: import pandas as pd

In [2]: df = pd.read_csv('Test.csv', index_col=0, parse_dates=True)

这会产生一个表示时区朴素 utc 时间的索引:

In [3]: df.index

Out[3]: DatetimeIndex(['2016-07-01 09:05:07', '2016-07-01 09:05:09',
           '2016-07-01 09:05:10', '2016-07-01 09:05:11',
           '2016-07-01 09:05:12', '2016-07-01 09:05:13',
           '2016-07-01 09:05:14', '2016-07-01 09:05:15'],
          dtype='datetime64[ns]', name='DateTime', freq=None)

我尝试使用 date_parser 函数:

In [4]: date_parser = lambda x: pd.to_datetime(x).tz_localize(None)

In [5]: df = pd.read_csv('Test.csv', index_col=0, parse_dates=True, date_parser=date_parser)

这给出了相同的结果。

我怎样才能让 read_csv 创建一个 DatetimeIndex,它是时区天真的 并代表 本地时间 而不是 utc 时间

我正在使用熊猫 0.18.1。

【问题讨论】:

你看this了吗? 是的,我做到了。但这个具体问题是关于处理实际存在的时区信息。在我的问题中,pandas.read_csv 通过将从 csv 读取的日期时间转换为时区天真的 utc 日期时间来丢失时区信息。 【参考方案1】:

根据the docs默认date_parser使用dateutil.parser.parser。根据the docs for that function,默认是忽略时区。因此,如果您提供 dateutil.parser.parser 作为 date_parser kwarg,则不会转换时区。

import dateutil

df = pd.read_csv('Test.csv', index_col=0, parse_dates=True, date_parser=dateutil.parser.parse)

print(df)

输出

                           Temperature
DateTime                              
2016-07-01 11:05:07+02:00       21.125
2016-07-01 11:05:09+02:00       21.138
2016-07-01 11:05:10+02:00       21.156
2016-07-01 11:05:11+02:00       21.179
2016-07-01 11:05:12+02:00       21.198
2016-07-01 11:05:13+02:00       21.206
2016-07-01 11:05:14+02:00       21.225
2016-07-01 11:05:15+02:00       21.233

【讨论】:

这个答案肯定有帮助,但会导致时区感知 DatetimeIndex。在解析函数中添加参数ignoretz=True 会给出所需的时区天真日期时间索引。我将此添加为问题的新答案。【参考方案2】:

Alex 的answer 导致了一个时区感知 DatetimeIndex。要按照 OP 的要求获取 本地时区 DatetimeIndex,请通过设置 ignoretz=True 通知 dateutil.parser.parser 忽略时区信息:

import dateutil

date_parser = lambda x: dateutil.parser.parse(x, ignoretz=True)
df = pd.read_csv('Test.csv', index_col=0, parse_dates=True, date_parser=date_parser)

print(df)

输出

                     Temperature
DateTime                        
2016-07-01 11:05:07       21.125
2016-07-01 11:05:09       21.138
2016-07-01 11:05:10       21.156
2016-07-01 11:05:11       21.179
2016-07-01 11:05:12       21.198
2016-07-01 11:05:13       21.206
2016-07-01 11:05:14       21.225
2016-07-01 11:05:15       21.233

【讨论】:

【参考方案3】:

我今天早些时候采用了dateutil 技术,但后来改用了更快的替代方案:

date_parser = lambda ts: pd.to_datetime([s[:-5] for s in ts]))

编辑:s[:-5] 正确(截图有错误)

在下面的屏幕截图中,我导入了大约 55MB 的制表符分隔文件。 dateutil 方法有效,但花费的时间要长几个数量级。

这是使用 pandas 0.18.1 和 dateutil 2.5.3。


编辑即使Z-0000 后缀丢失,这个 lambda 函数也可以工作...

date_parser = lambda ts: pd.to_datetime([s[:-5] if 'Z' in s else s for s in ts])

【讨论】:

【参考方案4】:

你甚至可以试试:

date_parser = lambda x : pd.to_datetime(x.str[:-6])

【讨论】:

A virtually identical solution 已在 4 年前发布。

以上是关于如何在熊猫中使用 read_csv 将时区感知日期时间作为时区天真的本地 DatetimeIndex 读取?的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中获取时区感知午夜日期时间? [复制]

如何在 django 中获取时区感知日期?

如何在 SqlAlchemy / Mysql 中存储时区感知日期时间值?

如何在 Python 中结合时区感知日期和时间?

python - 如何在没有dateutil的情况下将时区感知字符串转换为Python中的日期时间?

如何使用时区感知日期过滤模型?