#python #csv #date #command-line #compare
Вопрос:
Я пытаюсь сравнить 2 столбца временных меток в файле CSV, и я хочу сохранить только строки, в которых дата / время в столбце 1 предшествует дате / времени в столбце 2. Я не совсем уверен, с чего начать, поскольку мы рассматриваем сравнение многих разных чисел (например, месяц, год, час, минута и т. Д.) Отдельно Друг от друга, Включая сравнение AM / PM.
Пример: (дата в формате [мм / дд / гггг])
20.11.2018 3:00:13 вечера | 23.11.2017 6:45:00 |
22.12.2019 16:00:12 | 1/10/2020 4:50:11 утра |
10/10/2018 2:02:19 вечера | 07.10.2018 1:04:15 вечера |
Здесь я хотел бы сохранить строку 2, потому что дата в столбце 2 идет после даты в столбце 1, и я бы не хотел сохранять строки 1 и 3. Есть ли аккуратный способ сделать это в командной строке? (Если нет, любые указатели на написание скрипта Python были бы очень полезны)
Заранее спасибо!
Комментарии:
1. Есть ли какой-либо конкретный язык, который вы хотите использовать для этого? Подходит ли вам Ruby?
2. Я не знаком с Ruby, если это невозможно сделать в командной строке, то мне больше всего нравится Python!
3. Если ваш CSV-файл не содержит данных в кавычках (например, для экранирования запятых), вы можете проанализировать его напрямую с помощью оболочки, но проще использовать язык, который имеет анализатор CSV, такой как Perl, Python или Ruby; дальнейшая обработка также будет проще.
Ответ №1:
В Python вам просто нужно преобразовать каждое из значений даты в datetime
объекты. Затем их можно легко сравнить с помощью простого <
оператора. Например:
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-файл содержит заголовок, раскомментируйте две строки. Вы можете найти дополнительную информацию о том, как работает строка формата .strptime()
, в документации функции.
Этот подход использует встроенную функциональность Python и поэтому не требует установки дополнительных модулей.
Ответ №2:
Я постараюсь сделать это как можно более понятным и подробным, чтобы все могли понять :
1) Сначала я импортировал библиотеку datetime в 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
печать одной даты из нашего набора данных для проверки шаблона :
Имейте в виду, что индексация в python начинается с нуля
dataset[1][0] # dataset[row][column]
2.2) Шаблон — месяц / день / год час: мин: сек утра / вечера
pattern = "%m/%d/%Y %I:%M:%S %p"
вы можете проверить коды юридического формата, чтобы в будущем создать другой шаблон.
3) Теперь преобразуем даты нашего набора данных в объект date time, используя библиотеку, которую мы импортировали
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) Теперь мы вручную сравним даты, чтобы понять концепции.
просто используя операторы сравнения, мы можем сравнивать даты в python, используя библиотеку datetime
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
import csv
with open("new_dates.csv" , "w" , newline = "") as file :
writer = csv.writer(file)
writer.writerows(lst)
Результат :
Новый csv-файл с именем new_dates.csv будет создан в том же каталоге, что и ваш файл кода python. Этот файл будет содержать только те строки, в которых дата столбца 2 больше даты столбца 1.
Комментарии:
1. Если я не ошибаюсь, вы загружаете весь CSV в память, что имеет некоторые оговорки. Кстати, отличные объяснения 😉
Ответ №3:
Использование 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")
Ответ №4:
С помощью инструментов командной строки вы можете использовать awk
: для преобразования 1-й даты в формат эпохи:
echo "11/20/2018 3:00:13 PM" |gawk -F'[/:]' '{print mktime($3" "$1" "$2" "$4" "$5" "$6" "$7)}'
то же самое для второго поля. А затем вычтите столбец 2 из столбца 1. Если результат положительный, это означает, что столбец 1 находится после столбца 2
Здесь используется функция mktime
, из awk
которой выполняется «волшебство». Имейте в виду, что эта функция недоступна в некоторых версиях UNIX awk
Комментарии:
1. Я не знаю, как это произошло, но я отклонил ваш ответ; пожалуйста, отредактируйте свой пост, чтобы я мог его отменить
2. @Fravadona, не стесняйтесь отменить это 🙂
Ответ №5:
Я сохранил предоставленный вами образец в файле, разделенном табуляцией, без заголовков. Я импортировал его как DataFrame
using (обратите внимание, что я указал ваш формат даты в 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")
Чтобы выбрать нужные вам строки:
df.loc[df.loc[:,"col2"]>df.loc[:,"col1"],:]
Ответ №6:
Вы можете использовать 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