在 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 的 dayfirst
和 yearfirst
选项更改此行为。 (见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 进行排序的主要内容,如果未能解决你的问题,请参考以下文章