在 Python 中按日期对 CSV 进行排序

Posted

技术标签:

【中文标题】在 Python 中按日期对 CSV 进行排序【英文标题】:Sort a CSV by date in Python 【发布时间】:2010-12-18 22:29:04 【问题描述】:

我正在尝试对 CSV 文件进行排序,我希望项目按日期以相反的顺序排序:最新的优先。

def SortCsvByField( filename, fieldNo, sep = ',' ):
   records = [line.split(sep) for line in file(filename)]

这很容易,但我如何比较日期?

【问题讨论】:

你展示的内容很简单,但也很脆弱。最好使用 Python 的 CSV 库:docs.python.org/library/csv.html 关于比较日期(我假设某些日期在每一行的特定列中),您可以使用 datetime 模块:docs.python.org/library/datetime.html。您可以在日期对象上使用标准比较运算符。 这取决于日期的格式 【参考方案1】:

我建议安装出色的 dateutil 模块。 (在 Ubuntu/Debian 中,它由 python-dateutil 包提供)。

dateutil 可以将日期字符串解析为日期时间对象:它可以处理许多不同的日期格式,而无需您费力(*):

import dateutil.parser as dparser
date=dparser.parse("Mon May 7 1883 10:36:28")
print(date)
# 1883-05-07 10:36:28

date=dparser.parse("1685-3-21")
print(date)
# 1685-03-21 00:00:00

date=dparser.parse("12/17/1770")
print(date)
# 1770-12-17 00:00:00

请注意,解析将“12/17/1770”解释为“MM/DD/YYYY”形式。您可以使用 parse 的 dayfirstyearfirst 选项更改此行为。 (见http://labix.org/python-dateutil)

print(type(date))
# <type 'datetime.datetime'>

日期时间对象可以轻松排序:

dates=[dparser.parse("Mon May 7 1883 10:36:28"),dparser.parse("1685-3-21"),dparser.parse("12/17/1770"),]
dates.sort()
print(dates)
# [datetime.date(1685, 3, 21), datetime.date(1770, 12, 17), datetime.date(1833, 5, 7)]

如果您不想安装 dateutil 软件包,那么您将 必须推出自己的将日期字符串转换为日期时间对象的方法。这需要更多的工作,因为您必须定义格式。下面,'%Y-%m-%d' 定义了 YYYY-MM-DD 格式。有关可用格式代码的更多信息,请参阅http://au2.php.net/strftime(或 strftime 的手册页)。

例如,

dates=[datetime.datetime.strptime(date_str,'%Y-%m-%d') for date_str in
       ('1883-5-7','1685-3-21','1770-12-17',)]
print([str(date) for date in dates])
# ['1883-05-07 00:00:00', '1685-03-21 00:00:00', '1770-12-17 00:00:00']
dates.sort()
print([str(date) for date in dates])
# ['1685-03-21 00:00:00', '1770-12-17 00:00:00', '1883-05-07 00:00:00']

要在将日期时间对象转换回可打印字符串时控制格式,可以使用 datetime.datetime.strftime() 方法。

【讨论】:

(1)“如果你使用的是linux”??是否有一些平台依赖于 dateutil?它似乎在 Windows 上运行良好 [但请参阅下面的第 3 点] (2) 日期前面有 #,例如# 2009-09-25 10:36:28?? print() 的输出?如果是这样,他们就错了。应该是例如1883-05-07 10:36:28 (3) 对于那些坚持DD/MM/YYYY 公约的人来说,它将把"01/02/2009" 解释为二月的第一天,而不用举手投足,对吗?它不会做一些讨厌的事情,比如默默地将"31/12/2008" 设为 12 月 31 日,同时将 "01/02/2009" 设为 1 月 2 日,对吗? 这是一个好的开始,但您还没有解决它欣然接受混合 dd/mm 和 mm/dd 日期的问题,默认情况下 (AFAICT) 没有选择“严格”行为的选项。 我不明白为什么它默认将 10-19 附加到 'month,date'-less 日期。例如 1946 --> 1946-10-19 和 46 --> 2046-10-19.. 我们可以更改默认行为吗? @ThinkCode:因为今天是 10 月 19 日,所以添加了 10-19。您希望 dparser.parse('1946') 返回什么? 哎呀,我怎么会错过呢!好吧,我将此应用于出生日期列,而那些只有 1946 年的列显示为 1946-10-19。感谢您清理它。我们指定应该应用的默认日期/月份将使它更棒。我猜只是如果 else 会阻塞。谢谢拼错的Ubuntu!【参考方案2】:

如果您的日期是 ISO-8601 格式 (YYYY-MM-DD),那么您可以将它们排序为字符串,否则您必须先解析它们 (datetime.strptime)。

如果日期是第二个字段,您可以使用例如sorted(records, key=lambda a:a[1]) 进行排序。

【讨论】:

【参考方案3】:

假设您知道日期的格式,并且它们位于 CSV 文件的第 1 列中:

>>> import csv
>>> from datetime import datetime
>>> def date_key(row):
        return datetime.strptime(row[1].strip(), "%m/%d/%Y")

>>> with open('c:\\temp\\test\\date_test.csv', 'rb') as f:
        data = list(csv.reader(f))

>>> data
[['foo', ' 3/11/2004'], ['bar', ' 2/15/2001'], ['baz', '11/15/2007'], ['bat', '10/13/2002']]
>>> data.sort(key=date_key)
>>> data
[['bar', ' 2/15/2001'], ['bat', '10/13/2002'], ['foo', ' 3/11/2004'], ['baz', '11/15/2007']]

【讨论】:

以上是关于在 Python 中按日期对 CSV 进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在python中按日期时间对字典列表进行排序

在Python 3.4中按日期对字典列表进行排序[重复]

如何在 Pandas 数据框中按行值对日期时间列进行排序?

在Python中按日期对excel文件进​​行排序[关闭]

如何在飞镖/颤振中按日期对列表进行排序/排序?

如何在 MongoDB 中按日期对集合进行排序?