如何比较 csv 的 2 个不同列中的 2 个日期,以判断第 1 列中的日期是否在第 2 列之前

How to compare 2 dates in 2 different columns of a csv to tell if the date in column 1 comes before column 2

我正在尝试比较 CSV 文件中的 2 列时间戳,我只想保留第 1 列中的 date/time 在第 2 列中的 date/time 之前的行。我不太确定从哪里开始,因为我们正在考虑比较许多不同的数字(例如月、年、小时、分钟等),包括 AM/PM 比较。

示例:(日期为 [mm/dd/yyyy] 格式)

11/20/2018 3:00:13 PM 11/23/2017 6:45:00 AM
12/22/2019 4:00:12 PM 1/10/2020 4:50:11 AM
10/10/2018 2:02:19 PM 10/07/2018 1:04:15 PM

这里我想保留第 2 行,因为第 2 列中的日期在第 1 列中的日期之后,我不想保留第 1 行和第 3 行。在命令行中有没有一种巧妙的方法可以做到这一点? (如果没有,任何编写 Python 脚本的指示都会非常有帮助)

提前致谢!

在Python中,您只需将每个日期值转换为datetimeobjects。然后可以很容易地将它们与简单的 < 运算符进行比较。例如:

from datetime import datetime
import csv

with open('input.csv') as f_input, open('output.csv', 'w', newline='') as f_output:
    csv_input = csv.reader(f_input)
    #header = next(csv_input)   
    csv_output = csv.writer(f_output)
    #csv_output.writerow(header)
    
    for row in csv_input:
        date_col1 = datetime.strptime(row[0], '%m/%d/%Y %I:%M:%S %p')
        date_col2 = datetime.strptime(row[1], '%m/%d/%Y %I:%M:%S %p')
        
        if date_col1 < date_col2:
            csv_output.writerow(row)

如果您的 CSV 文件包含 header,请取消注释这两行。您可以在 .strptime() 函数文档中找到有关格式字符串如何工作的更多信息。

此方法使用内置 Python 功能,因此不需要安装更多模块。

我已将您提供的示例保存在制表符分隔的文件中 - 没有 headers。我已将其导入为 DataFrame 使用(请注意,我在 date_parser 中指定了您的日期格式):

import pandas as pd
import datetime as dt

df = pd.read_csv(PATH_TO_YOUR_FILE, sep="\t", names=["col1", "col2"], parse_dates=[0,1], date_parser=lambda x:dt.datetime.strptime(x, "%m/%d/%Y %I:%M:%S %p")

到select你需要的行:

df.loc[df.loc[:,"col2"]>df.loc[:,"col1"],:]

借助命令行工具,您可以使用 awk: 将第一个日期转换为纪元格式:

echo "11/20/2018 3:00:13 PM" |gawk -F'[/:]' '{print mktime(" "" "" "" "" "" ")}'

第二个字段相同。然后从第 1 列中减去第 2 列。如果结果为正,则表示第 1 列在第 2 列之后 这里使用了 awk 中的函数 mktime 来实现“魔法”。请注意此功能在某些 UNIX awk 版本

中不可用

您可以使用pd.to_datetime解析日期时间字符串,然后将它们的比较作为条件来过滤所需的行。

演示:

import pandas as pd

df = pd.DataFrame({
    'start': ['11/20/2018 3:00:13 PM', '12/22/2019 4:00:12 PM', '10/10/2018 2:02:19 PM'],
    'end': ['11/23/2017 6:45:00 AM', '1/10/2020 4:50:11 AM', '10/07/2018 1:04:15 PM']
})

result = pd.DataFrame(df[
                pd.to_datetime(df['start'], format='%m/%d/%Y %I:%M:%S %p') <
                pd.to_datetime(df['end'], format='%m/%d/%Y %I:%M:%S %p')
            ])

print(result)

输出:

                   start                   end
1  12/22/2019 4:00:12 PM  1/10/2020 4:50:11 AM

ONLINE DEMO

使用Pandas

import pandas as pd

# Read tab delimited CSV file without header
# Names columns date1, date2
df = pd.read_csv("dates.csv", 
                  header = None,
                  sep='\t', 
                  parse_dates = [0, 1],        # use default date parser i.e. parser.parser
                  names=["date1", "date2"])

# Filter (keep) row when date2 > date1
df = df[df.date2 > df.date1]

# Output to filtered CSV file using the original date format
df.to_csv('filtered_dates.csv', index = False, header = False, sep = '\t', date_format  = "%Y/%m/%d %I:%M:%S %p")

我会尽量保持清晰和详细,以便每个人都能理解:

1) 首先我导入了python的日期时间库

import datetime as dt

2) 现在我正在导入我必须处理的 csv 文件,在这种情况下我使用了 dates.csv与上述问题中的数据相同:

from csv import reader
dataset = list(reader(open("dates.csv", encoding = "utf-8")))

2.1) 打印数据集以检查其是否正常工作:

dataset

从我们的数据集中打印单个日期以检查模式:

Keep in mind that indexing in python starts with zero

dataset[1][0] # dataset[row][column]

2.2) 模式是 month/day/year hour:min:sec AM/PM

pattern = "%m/%d/%Y %I:%M:%S %p" 

您可以勾选 Legal Format Codes 以便将来创建不同的模式。

3) 现在将我们的数据集日期转换为日期时间 object 使用我们导入的库

    for i in dataset[1:]: 
# [1:] because 1st row has heading and we don't need it

        i[0] = dt.datetime.strptime(i[0],pattern)
        i[1] = dt.datetime.strptime(i[1],pattern)

    print(dataset[1][0])

转换成功^

4) 现在我们将手动比较日期以理解概念。

by simply using comparison operators we can compare the dates in python using datetime library

print(dataset[2][0] , "and" , dataset[2][1])
print(dataset[2][0] > dataset[2][1]) 

5) 现在创建一个单独的列表,其中仅添加第 2 列的日期大于第 1 列的日期的那些行:

col2_greatorthan_col1 = []

在我们的新列表中添加标题:

col2_greatorthan_col1.append(["column 1" , "column 2"])

比较每个日期并在我们的新列表中追加我们想要的行:

for i in dataset[1:]:
    if i[1] > i[0]: # means if column 2's date is greater than column 1's date
        col2_greatorthan_col1.append(i) # appending the filtered rows in our new list

col2_greatorthan_col1

6) 现在只需创建一个真实世界的 csv 文件,该文件将具有与 col2_greatorthan_col1[=29 相同的数据=]

import csv

with open("new_dates.csv" , "w" , newline = "") as file :
    writer = csv.writer(file)
    writer.writerows(lst)

结果:

一个名为 new_dates.csv 的新 csv 文件将在与您的 python 代码文件相同的目录中创建。 此文件将仅包含第 2 列的日期大于第 1 列的日期的那些行。