首页 > 解决方案 > 处理`read_csv`的本地时间变化缓慢的熊猫

问题描述

从时区偏移(夏令时)更改的大型 CSV 文件中读取时,parse_dates速度会变慢。你能建议我应该如何处理这个吗?对于某些工作,我确实转换为“UTC”,但我还需要使用原始本地时间。有没有办法强制解析列datetime64[ns]而不是 datetime64[ns, <offset>]?我认为添加列时间偏移可能是一种改进https://github.com/pandas-dev/pandas/issues/16898。我可能需要原始的幼稚时间戳。

pd.__version__
'0.24.2'

随着时间偏移的变化

import pandas as pd
from io import StringIO

data = StringIO("""date_time
2018-11-27 04:57:10+01:00
2018-11-27 04:57:10+02:00
2018-11-27 04:57:10+02:00
2018-11-27 04:57:10+02:00""")

df = pd.read_csv(data, sep=",", parse_dates =['date_time'])

输出

df.date_time

0    2018-11-27 04:57:10+01:00
1    2018-11-27 04:57:10+02:00
2    2018-11-27 04:57:10+02:00
3    2018-11-27 04:57:10+02:00
Name: date_time, dtype: object

我想我想要dtype: datetime64[ns]

没有时间偏移变化

import pandas as pd
from io import StringIO

data = StringIO("""date_time
2018-11-27 04:57:10+02:00
2018-11-27 04:57:10+02:00
2018-11-27 04:57:10+02:00
2018-11-27 04:57:10+02:00""")

df = pd.read_csv(data, sep=",", parse_dates =['date_time'])

输出

df.date_time

0   2018-11-27 04:57:10+02:00
1   2018-11-27 04:57:10+02:00
2   2018-11-27 04:57:10+02:00
3   2018-11-27 04:57:10+02:00
Name: date_time, dtype: datetime64[ns, pytz.FixedOffset(120)]

标签: pandas

解决方案


当您的数据在中间更改小时偏移量时,基于字符串的常规解析方法将简单地将这些偏移量更改传递为不同的未命名时区。Pandas 的问题在于它不能将一列表示为包含多个 time zone,而是将该列表示为object. 为了解决这个问题,我们需要将每个值显式转换为单个命名时区。这使得 Pandas 可以使用,例如,datetime64[ns, America/New_York]作为列的类型,如果列中的所有值都具有相同的时区,它将自动执行此操作。更改的小时偏移量由该时区定义定义,因此信息被保留。缺点是您必须知道指定的时区才能使用您的数据。

我使用了几种方法来评估速度差异。无论出于何种原因,内置的 Pandas 功能to_datetime()都非常慢。相反,我会根据您的数据建议一种替代方法,自己执行文本到日期时间的转换。以您喜欢的方式创建 Pythondatetime对象,应用时区,然后转换为 PandasTimestamp类型。如果您对ciso8601具有快速字符串到 ISO8601 解析的外部库感到满意,则可以使用以下方法。您还需要pytz具有时区定义的流行库。

假设您有一个名为 CSV 的文件filename,其中有一Timestamp列带有 ISO8601 时间戳。

import ciso8601
import pandas as pd
import pytz

TIME_ZONE = 'America/New_York'

def custom_parse(val):
    iso_time = ciso8601.parse_datetime(val)
    tz_time = iso_time.astimezone(pytz.timezone(TIME_ZONE))
    pd_time = pd.Timestamp(tz_time)
    return pd_time

dt = pd.read_csv(filename, parse_dates=['Timestamp'], date_parser=custom_parse)

如果您不想使用ciso8601,您可以iso_time =用基于正则表达式的解析步骤替换该步骤,或者datetime.datetime.strptime()等。几乎任何东西都会比to_datetime()Pandas 提供的更快。


推荐阅读