如何让 pandas.read_csv() 从 CSV 文件列中推断 datetime 和 timedelta 类型?

Posted

技术标签:

【中文标题】如何让 pandas.read_csv() 从 CSV 文件列中推断 datetime 和 timedelta 类型?【英文标题】:How to get pandas.read_csv() to infer datetime and timedelta types from CSV file columns? 【发布时间】:2014-03-21 07:57:34 【问题描述】:

pandas.read_csv() 推断列的类型,但我无法让它推断任何日期时间或 timedelta 类型(例如datetime64timedelta64)的值似乎是明显的日期时间和时间增量的列。

这是一个示例 CSV 文件:

datetime,timedelta,integer,number,boolean,string
20111230 00:00:00,one hour,10,1.6,True,Foobar

还有一些用 pandas 阅读的代码:

dataframe = pandas.read_csv(path)

该数据帧上列的类型为 object、object、int、float、bool、object。除了前两列,我希望它们是 datetime 和 timedelta 之外,它们都符合我的预期。

是否可以让 pandas 自动检测 datetime 和 timedelta 列?

(我不想告诉 pandas 哪些列是 datetimes 和 timedeltas 或告诉它格式,我希望它尝试自动检测它们,就像它对 into、float 和 bool 列所做的那样。)

【问题讨论】:

to_timedelta 在 0.13 中可用:pandas.pydata.org/pandas-docs/version/0.13.0/…;与to_datetime 一致,您可以尝试转换列。他们不是automatic 从字符串中执行此操作的方法。它太模棱两可了。 【参考方案1】:

这就是我将它用于日期时间格式的多个列的方式。

parse_dates=['Start-time', 'End-time', 'Manufacturing date',
                                'Expiry Date'], infer_datetime_format=True

infer_datetime_format=True 很好,因为它会忽略任何不是日期时间格式的列。这让我认为,如果有一种方法可以将代码应用于 csv 文件中的所有列,那可能会很好。特别是如果您有 30 个或更多列将dtypes 声明为日期时间。但它不适用于 timedelta64。

【讨论】:

【参考方案2】:

您可以做的一件事是使用strptime 定义您的日期解析器,这将处理您的日期格式,但这不是自动的:

In [59]:

import pandas as pd
import datetime as dt

def parse_dates(x):
    return dt.datetime.strptime(x, '%Y%m%d %H:%M:%S')
# dict for word lookup, conversion
word_to_int='zero':0,
     'one':1,
     'two':2,
     'three':3,
     'four':4,
     'five':5,
     'six':6,
     'seven':7,
     'eight':8,
     'nine':9


def str_to_time_delta(x):
    num = 0
    if 'hour' in x.lower():
        num = x[0:x.find(' ')].lower()
    return dt.timedelta( hours = word_to_int[num])
df = pd.read_csv(r'c:\temp1.txt', parse_dates=[0],date_parser=parse_dates)
df.dtypes
Out[59]:
datetime     datetime64[ns]
timedelta            object
integer               int64
number              float64
boolean                bool
string               object
dtype: object
In [60]:

然后转换为 timedeltas 使用 dict 和函数解析并转换为 timedeltas

df['timedelta'] = df['timedelta'].map(str_to_time_delta)

In [61]:

df.dtypes
Out[61]:
datetime      datetime64[ns]
timedelta    timedelta64[ns]
integer                int64
number               float64
boolean                 bool
string                object
dtype: object
In [62]:

df
Out[62]:
             datetime  timedelta  integer  number boolean  string
0 2011-12-30 00:00:00   01:00:00       10     1.6    True  Foobar

[1 rows x 6 columns]

要回答您的主要问题,我不知道有什么方法可以自动执行此操作。

编辑

您可以这样做,而不是我的复杂映射函数:

df['timedelta'] = pd.to_timedelta(df['timedelta'])

进一步编辑

正如@Jeff 所说,您可以在读取 csv 时执行此操作,而不是使用 strptime(但在 0.13.1 及更高版本中):

df = pd.read_csv(r'c:\temp1.txt', parse_dates=[0], infer_datetime_format=True)

【讨论】:

to_timedelta 取代了实际解析时间增量的需要(在 0.13.0 中可用) 这里不需要date_parser功能parse_dates=[0]也可以,也可以开启infer_datetime_format自动获取日期,看这里:pandas.pydata.org/pandas-docs/stable/whatsnew.html#enhancements(还是要指定列) @Jeff 不适用于 0.13.1,所以看来我必须使用我的自定义解析器 你必须指定parse_dates[0] ALWAYS @Jeff 是的,这可行,但这与在线文档相矛盾:pandas.pydata.org/pandas-docs/stable/whatsnew.html#enhancements 其中指出 parse_dates 应设置为 True,感谢您的澄清,但如何更正文档?

以上是关于如何让 pandas.read_csv() 从 CSV 文件列中推断 datetime 和 timedelta 类型?的主要内容,如果未能解决你的问题,请参考以下文章

pandas read_csv,最后一列包含逗号

如何在 pandas.read_csv 的标题之前跳过未知数量的空行?

如何使用 pandas.read_csv 在双引号之间读取带有千位分隔符的数字 [重复]

获取 pandas.read_csv 以将空值读取为空字符串而不是 nan

pandas read_csv 列 dtype 设置为十进制但转换为字符串

使用 pandas.read_csv 从 URL 读取压缩的 CSV 文件时出错