如何比较 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中,您只需将每个日期值转换为datetime
objects。然后可以很容易地将它们与简单的 <
运算符进行比较。例如:
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
使用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 列的日期的那些行。
我正在尝试比较 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中,您只需将每个日期值转换为datetime
objects。然后可以很容易地将它们与简单的 <
运算符进行比较。例如:
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
使用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 列的日期的那些行。