Pandas 能自动从 CSV 文件中读取日期吗?

2025-02-10 08:57:00
admin
原创
47
摘要:问题描述:今天,我惊喜地发现,当从数据文件读取数据时(例如),pandas 能够识别值的类型:df = pandas.read_csv('test.dat', delimiter=r"s+", names=['col1','col2','col3']) 例如可以通过以下方式检查:for i...

问题描述:

今天,我惊喜地发现,当从数据文件读取数据时(例如),pandas 能够识别值的类型:

df = pandas.read_csv('test.dat', delimiter=r"s+", names=['col1','col2','col3'])

例如可以通过以下方式检查:

for i, r in df.iterrows():
    print type(r['col1']), type(r['col2']), type(r['col3'])

尤其是整数、浮点数和字符串被正确识别。但是,我有一列包含以下格式的日期:2013-6-4。这些日期被识别为字符串(而不是 python 日期对象)。有没有办法让 pandas“学习”识别日期?


解决方案 1:

您应该在读取时添加parse_dates=Trueparse_dates=['column name'],这通常足以神奇地解析它。但总是有一些奇怪的格式需要手动定义。在这种情况下,您还可以添加日期解析器函数,这是最灵活的方式。

假设您有一个包含字符串的列“datetime”,那么:

from datetime import datetime
dateparse = lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S')

df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)

这样,您甚至可以将多列组合成一个日期时间列,这会将“日期”和“时间”列合并为一个“日期时间”列:

dateparse = lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S')

df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)

您可以在此页面中strptime找到和的指令(即用于不同格式的字母)。strftime

解决方案 2:

也许自从@Rutger回答以来,pandas 接口已经发生了变化,但在我使用的版本 (0.15.2) 中,该date_parser函数接收的是日期列表,而不是单个值。在这种情况下,他的代码应该像这样更新:

from datetime import datetime
import pandas as pd

dateparse = lambda dates: [datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in dates]
    
df = pd.read_csv('test.dat', parse_dates=['datetime'], date_parser=dateparse)

由于最初的提问者说他​​想要日期,并且日期是格式化的2013-6-4,所以该dateparse函数实际上应该是:

dateparse = lambda dates: [datetime.strptime(d, '%Y-%m-%d').date() for d in dates]

解决方案 3:

您可以pandas.to_datetime()按照文档中的建议使用pandas.read_csv()

如果列或索引包含无法解析的日期,则整个列或索引将以对象数据类型原封不动地返回。对于非标准日期时间解析,请使用pd.to_datetimeafter pd.read_csv

演示:

>>> D = {'date': '2013-6-4'}
>>> df = pd.DataFrame(D, index=[0])
>>> df
       date
0  2013-6-4
>>> df.dtypes
date    object
dtype: object
>>> df['date'] = pd.to_datetime(df.date, format='%Y-%m-%d')
>>> df
        date
0 2013-06-04
>>> df.dtypes
date    datetime64[ns]
dtype: object

解决方案 4:

Pandas 2.0 更新

作为使 Pandas 2.0 中的日期时间处理更加可靠的广泛尝试的一部分,日期解析(尤其是在 CSV 文件上)已经出现了许多向后不兼容的更改和弃用。许多其他答案推荐的infer_datetime_formatdate_parser参数现在都已弃用(有关原因,请参阅PDEP-4和此问题)。

现在解析已知格式的日期的正确方法是使用parse_datesdate_format参数pd.read_csv()

单列,自动检测格式

df = pd.read_csv(
    infile,
    parse_dates=['My DateTime']
)

具有已知格式的单列

df = pd.read_csv(
    infile,
    parse_dates=['My DateTime'],
    date_format={'My DateTime': '%Y-%m-%d %H:%M:%S'}
)

合并已知格式的列

df = pd.read_csv(
    infile,
    parse_dates={'mydatetime': ['My Date', 'My Time']},
    # mydatetime will contain my_date and my_time separated by a single space
    date_format={'mydatetime': '%Y-%m-%d %H:%M:%S'}
)

如果您的日期解析逻辑比使用静态格式字符串所能完成的更复杂,例如如果您在同一列上有多种日期格式,或者正在高级使用date_parser,则鼓励您按照文档read_csv(查看参数)在读取文件时parse_dates将列保留为默认类型,并在第二遍中使用进行日期转换,如下所示。object`pd.to_datetime`

Pandas v1 答案

除了其他回复所说的内容之外,如果您必须解析包含数十万个时间戳的超大文件,date_parser则可能会成为一个巨大的性能瓶颈,因为它是每行调用一次的 Python 函数。通过在解析 CSV 文件时将日期保留为文本,然后一次性将整个列转换为日期,您可以获得相当大的性能改进:

# For a data column
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']})

df['mydatetime'] = pd.to_datetime(df['mydatetime'], exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
# For a DateTimeIndex
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']}, index_col='mydatetime')

df.index = pd.to_datetime(df.index, exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
# For a MultiIndex
df = pd.read_csv(infile, parse_dates={'mydatetime': ['date', 'time']}, index_col=['mydatetime', 'num'])

idx_mydatetime = df.index.get_level_values(0)
idx_num = df.index.get_level_values(1)
idx_mydatetime = pd.to_datetime(idx_mydatetime, exact=True, cache=True, format='%Y-%m-%d %H:%M:%S')
df.index = pd.MultiIndex.from_arrays([idx_mydatetime, idx_num])

对于我的使用情况,一个文件有 200k 行(每行一个时间戳),处理时间从大约一分钟缩短到不到一秒。

解决方案 5:

将两列合并为一个日期时间列时,接受的答案会产生错误(pandas 版本 0.20.3),因为两列被分别发送到 date_parser 函数。

以下工作:

def dateparse(d,t):
    dt = d + " " + t
    return pd.datetime.strptime(dt, '%d/%m/%Y %H:%M:%S')

df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)

解决方案 6:

pandas read_csv 方法非常适合解析日期。完整文档位于http://pandas.pydata.org/pandas-docs/stable/generated/pandas.io.parsers.read_csv.html

您甚至可以将不同的日期部分放在不同的列中并传递参数:

parse_dates : boolean, list of ints or names, list of lists, or dict
If True -> try parsing the index. If [1, 2, 3] -> try parsing columns 1, 2, 3 each as a
separate date column. If [[1, 3]] -> combine columns 1 and 3 and parse as a single date
column. {‘foo’ : [1, 3]} -> parse columns 1, 3 as date and call result ‘foo’

默认的日期感知效果很好,但似乎偏向北美日期格式。如果你住在其他地方,你可能会偶尔被结果所困扰。据我所知,1/6/2000 在美国表示 1 月 6 日,而我住的地方表示 6 月 1 日。如果使用 23/6/2000 这样的日期,它会很聪明地将它们调换。不过,使用 YYYYMMDD 日期变体可能更安全。在此向 pandas 开发人员致歉,但我最近没有用本地日期进行测试。

您可以使用 date_parser 参数传递一个函数来转换格式。

date_parser : function
Function to use for converting a sequence of string columns to an array of datetime
instances. The default uses dateutil.parser.parser to do the conversion.

解决方案 7:

是的 - 根据pandas.read_csv 文档:

注意: iso8601 格式的日期存在快速路径。

因此,如果您的 csv 有一个名为的列datetime,并且日期看起来像2013-01-01T01:01这样,运行此命令将使 pandas(我在 v0.19.2 上)自动获取日期和时间:

df = pd.read_csv('test.csv', parse_dates=['datetime'])

请注意,您需要明确传递parse_dates,否则它不起作用。

验证方式:

df.dtypes

您应该看到该列的数据类型是datetime64[ns]

解决方案 8:

加载包含日期列的 csv 文件时,我们有两种方法可以让 pandas 识别日期列,即

  1. Pandas 通过参数明确识别格式date_parser=mydateparser

  2. Pandas 通过 agr 隐式识别格式infer_datetime_format=True

一些日期列数据

2018 年 1 月 1 日

2018 年 1 月 2 日

这里我们不知道前两件事,可能是月份或日期。所以在这种情况下,我们必须使用方法 1:- 明确传递格式

    mydateparser = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
    df = pd.read_csv(file_name, parse_dates=['date_col_name'],
date_parser=mydateparser)

方法 2:隐式或自动识别格式

df = pd.read_csv(file_name, parse_dates=[date_col_name],infer_datetime_format=True)

解决方案 9:

  • 分别读取日期和时间格式的现有字符串列


pd.read_csv('CGMData.csv', parse_dates=['Date', 'Time'])

结果列

在此处输入图片描述



  • 连接日期和时间的字符串列并添加日期类型对象的新列 - 删除原始列

  1. 如果要重命名新列名,则将其作为字典传递,如下例所示,新列名将是键名,

  2. 如果作为列列表传递,新列名将由列表中传递的列名连接而成,并以 _ 分隔,例如 Date_Time


    # parse_dates={'given_name': ['Date', 'Time']}    
    pd.read_csv("InsulinData.csv",low_memory=False, 
                                 parse_dates=[['Date', 'Time']])

    pd.read_csv("InsulinData.csv",low_memory=False, 
                                 parse_dates={'date_time': ['Date', 'Time']})

  • 连接日期和时间的字符串列并添加日期类型对象的新列并保留原始列


pd.read_csv("InsulinData.csv",low_memory=False, 
          parse_dates=[['Date', 'Time']], keep_date_col=True)

  • 想要在从 csv 读取时更改日期和时间的格式


parser = lambda x: pd.to_datetime(x, format='%Y-%m-%d %H:%M:%S')
pd.read_csv('path', date_parser=parser, parse_dates=['date', 'time'])

解决方案 10:

如果性能对您来说很重要,请确保您的时间:

import sys
import timeit
import pandas as pd

print('Python %s on %s' % (sys.version, sys.platform))
print('Pandas version %s' % pd.__version__)

repeat = 3
numbers = 100

def time(statement, _setup=None):
    print (min(
        timeit.Timer(statement, setup=_setup or setup).repeat(
            repeat, numbers)))

print("Format %m/%d/%y")
setup = """import pandas as pd
import io

data = io.StringIO('''\nProductCode,Date
''' + '''\nx1,07/29/15
x2,07/29/15
x3,07/29/15
x4,07/30/15
x5,07/29/15
x6,07/29/15
x7,07/29/15
y7,08/05/15
x8,08/05/15
z3,08/05/15
''' * 100)"""

time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'date_parser=lambda x: pd.datetime.strptime(x, "%m/%d/%y")); data.seek(0)')

print("Format %Y-%m-%d %H:%M:%S")
setup = """import pandas as pd
import io

data = io.StringIO('''\nProductCode,Date
''' + '''\nx1,2016-10-15 00:00:43
x2,2016-10-15 00:00:56
x3,2016-10-15 00:00:56
x4,2016-10-15 00:00:12
x5,2016-10-15 00:00:34
x6,2016-10-15 00:00:55
x7,2016-10-15 00:00:06
y7,2016-10-15 00:00:01
x8,2016-10-15 00:00:00
z3,2016-10-15 00:00:02
''' * 1000)"""

time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
     'date_parser=lambda x: pd.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")); data.seek(0)')

印刷:

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28) 
[Clang 6.0 (clang-600.0.57)] on darwin
Pandas version 0.23.4
Format %m/%d/%y
0.19123052499999993
8.20691274
8.143124389
1.2384357139999977
Format %Y-%m-%d %H:%M:%S
0.5238807110000039
0.9202787830000005
0.9832778819999959
12.002349824999996

因此,对于 iso8601 格式的日期(%Y-%m-%d %H:%M:%S显然是 iso8601 格式的日期,我猜可以删除T并用空格替换),您应该指定infer_datetime_format(这显然与更常见的日期也没有什么区别),并且传递您自己的解析器只会削弱性能。另一方面,date_parser对于不那么标准的日期格式确实有区别。像往常一样,在优化之前一定要计时。

解决方案 11:

您可以将参数date_parser与函数一起使用,将字符串列序列转换为日期时间实例数组:

parser = lambda x: pd.to_datetime(x, format='%Y-%m-%d %H:%M:%S')
pd.read_csv('path', date_parser=parser, parse_dates=['date_col1', 'date_col2'])

解决方案 12:

是的,这段代码运行起来非常简单。这里索引 0 指的是日期列的索引。

df = pd.read_csv(filepath, parse_dates=[0], infer_datetime_format = True)

解决方案 13:

不,pandas 没有办法自动识别日期列。

Pandas 在类型推断方面做得很差。它基本上将大多数列设置为通用object类型,除非你手动解决这个问题,例如使用上述parse_dates参数。

如果您想要自动检测列类型,则必须使用单独的数据分析工具,例如visions,然后将推断出的类型转换或反馈到DataFrame构造函数中(例如,对于日期和from_csv,使用parse_dates参数)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用