在 Pandas 中读取 CSV 文件时如何自动检测日期/日期时间列并设置它们的数据类型

源节点: 1106147

在 Pandas 中读取 CSV 文件时如何自动检测日期/日期时间列并设置它们的数据类型

当 read_csv( ) 读取例如“2021-03-04”和“2021-03-04 21:37:01.123”作为纯粹的“对象”数据类型时,通常您可以简单地一次将它们全部自动转换为真正的日期时间数据类型。


By 大卫 B 罗森(博士),IBM 全球融资部自动信贷审批首席数据科学家



假设我有一个 CSV 数据文件,我想将它读入 Pandas 数据框,其中的一些列是日期或日期时间,但我不想预先识别/指定这些列的名称。 相反,我想自动获取显示在 df.info() 输出如图 以上, 适当的列在哪里 自动 给定日期时间数据类型(绿色轮廓框)。 这是如何实现的:

from dt_auto import read_csv
df=read_csv('myfile.csv')

请注意,我做了 不能 直接调用上面的 pd.read_csv(read_csv 的 Pandas 版本)。 我的 dt_auto.read_csv 函数(参见下面的代码)调用了 pd.read_csv() 本身,然后自动检测并转换了两个检测到的日期时间列的数据类型。 (此 df 的内容将在下面显示。)

如果我使用常规的 Pandas pd.read_csv(),默认情况下我将仅获得通用对象数据类型,如下所示(红色轮廓框):

from pandas import read_csv
df=read_csv('myfile.csv')
df.info()



请注意,与原始代码的唯一区别在于导入语句中,我将“from dt_auto”更改为“from pandas”。 只要您始终只使用“=read_csv()”,而不是将其限定为“=pd.read_csv()”或“=dt_auto.read_csv()”,这就足够了。

这是我的内容 dt_auto.py (“日期时间自动”):

import pandas as pd
def dt_inplace(df): """Automatically detect and convert (in place!) each dataframe column of datatype 'object' to a datetime just when ALL of its non-NaN values can be successfully parsed by pd.to_datetime(). Also returns a ref. to df for convenient use in an expression. """ from pandas.errors import ParserError for c in df.columns[df.dtypes=='object']: #don't cnvt num try: df[c]=pd.to_datetime(df[c]) except (ParserError,ValueError): #Can't cnvrt some pass # ...so leave whole column as-is unconverted return df
def read_csv(*args, **kwargs): """Drop-in replacement for Pandas pd.read_csv. It invokes pd.read_csv() (passing its arguments) and then auto- matically detects and converts each column whose datatype is 'object' to a datetime just when ALL of the column's non-NaN values can be successfully parsed by pd.to_datetime(), and returns the resulting dataframe. """ return dt_inplace(pd.read_csv(*args, **kwargs))

但这不是有风险吗? 如果其中一列不完全是日期时间列怎么办? 当然,您可能有一些晦涩的字符串,它们碰巧看起来像日期但实际上不是,但是此代码盲目转换或丢失非日期时间字符串的风险不大,原因有两个:

  1. 此代码将 不能 转换列中的任何值,除非 每周 此列中的非 NaN 值可以通过 pd.to_datetime 成功解析并转换为日期时间。 换句话说,我们不会让它将字符串转换为 pd.NaT(“失败”结果),因为它无法将其理解为日期时间。
  2. 它会 不能 尝试转换已被解释为对象以外的任何类型的列,即任何特定类型,如 int64 或 float64,即使 pd.to_datetime 会很高兴(但可能不受欢迎)将 2000 之类的数字转换为日期 2000-01 -01.

到目前为止,根据我的经验,dt_auto.read_csv 函数在典型的数据帧上运行不需要很长时间。 即使有很多非日期时间对象(字符串)列,它几乎总是很快就会在每个此类列的顶部附近遇到一个值,该值无法解析为日期时间并放弃并移至下一列而不尝试解析列的其余值。

以下是 dt_auto.read_csv() 生成的数据帧的样子,尽管您不一定能通过查看它来判断两个适当的列确实是日期时间数据类型。 碰巧的是,CSV 文件在 Update_Timestamp 中的秒数具有不同的小数位数(三位、无和九位),但无论如何,日期时间数据类型本身都显示了九位这样的数字。 csv 文件中的生日实际上只有日期(没有时间),但存储为完整的日期时间,小时、分钟和秒为零(包括零作为小数部分),但列中的所有时间分量为零会导致 Pandas 仅显示此列的日期(年-月-日)。



当然,pd.to_datetime 以及 dt_auto.read_csv 默认无法处理所有可能的日期和日期时间格式,但它可以处理许多常见的明确(通常是年月日)格式,例如由 dataframe.to_csv 方法编写的格式和许多其他格式工具,包括许多 ISO 日期时间格式(通常有一个“T”将日期与时间分开,而不是一个空格)。 我还没有尝试过包含时区信息的日期时间,因为我通常不会看到这样的数据,但是请在回复评论中告诉我是否可以通过进一步更改代码来更好地处理这些数据。

你怎么认为? 你觉得这篇小文章有用吗? 并且 Pandas 本身是否应该添加(例如添加到 pd.read_csv 函数本身?)为我们选择性地执行此操作的功能,以便您不需要复制/导入我上面的 dt_auto.py 代码? 我很高兴在此处看到您的评论和问题作为答复。

 
感谢艾略特·冈恩。

 
简介: 大卫 B 罗森(博士) 是 IBM 全球融资部自动信贷审批的首席数据科学家。 找到更多大卫的作品,请访问 dabruro.medium.com.

原版。 经许可重新发布。

相关新闻:

资料来源:https://www.kdnuggets.com/2021/10/auto-detect-date-datetime-columns-and-set-their-datatype-when-reading-a-csv-file-in-pandas.html

时间戳记:

更多来自 掘金队