Фильтрация строк csv по данным столбца

#python #csv #filter

#python #csv #Фильтр

Вопрос:

Я не уверен, как это назвать, но у меня есть csv с данными:

 ...|Address    | Date       |...  
...|Abraham st.| 01/01/2008 |...  
...|Abraham st.| 02/02/2007 |...  
...|Abraham st.| 03/03/2011|...  
  

итак, что я хочу сделать, это сохранить только самую новую запись (в данном случае это будет row4), у меня действительно возникают проблемы с этим.

Моя первоначальная идея — прочитать данные из csv в список строк, а затем:

  1. для преобразования строк даты в объект datetime
  2. а затем просмотрите каждую строку, получите ее имя и сравните с любой другой строкой, чтобы найти самую высокую дату и сохранить строку даты.

есть ли лучший способ подойти к этому?

Комментарии:

1. сохраните строку даты куда?

2. @bpceee пока не уверен, но, скорее всего, к новому списку строк, которые я позже буду использовать для переопределения текущего файла.

Ответ №1:

Вместо этого следите за самым высоким значением, которое было замечено до сих пор; Я предполагаю, что здесь у вас уже есть csv.reader() объект, считывающий данные CSV:

 from datetime import datetime

max_date = datetime.min
newest_row = None

for row in csv_reader:
    # assumption: your date is the 4th column in each row
    date = datetime.strptime(row[3], '%m/%d/%Y')
    if date > max_date:
        # row is newer, remember it
        max_date = date
        newest_row = row
  

Когда вы прочитаете весь файл, newest_row будет сохранена строка данных с самой последней датой. Однако холод никогда не содержит более 2 строк в памяти (текущая обрабатываемая строка и самая новая строка, найденная на данный момент).

Обратите внимание, что я начал max_date с datetime.min , что является минимальным значением, которое вы можете сохранить в datetime объекте; пока ваш входной файл не содержит строк за 1 января 1 года, у вас все должно быть хорошо.

Ответ №2:

Просто используйте max встроенную функцию с key функцией, которая извлекает и преобразует поле даты в datetime объект. Я предполагаю, что ваши даты — мм / дд / гггг.

 import csv
from datetime import datetime

DATE_COLUMN = 1
with open('input.csv') as f:
    reader = csv.reader(f, delimiter='|')
    next(reader)    # skip over the CSV header row
    most_recent = max(reader, key=lambda x : datetime.strptime(x[DATE_COLUMN].strip(), '%d/%m/%Y'))

>>> print most_recent
['Abraham st.', ' 03/03/2011']
  

Я думаю, что ваше намерение состоит в том, чтобы сгруппироваться по столбцу «Адрес» и выбрать самую последнюю дату из столбца «Дата», и в этом случае вы можете использовать itertools.groupby() так:

 import csv
from itertools import groupby
from datetime import datetime

ADDRESS_COLUMN = 0
DATE_COLUMN = 1
most_recent = []

with open('input.csv') as f:
    reader = csv.reader(f, delimiter='|')
    next(reader)    # skip over the CSV header row
    for k, g in groupby(sorted(reader), lambda x : x[ADDRESS_COLUMN]):
        most_recent.append(max(g, key=lambda x : datetime.strptime(x[DATE_COLUMN].strip(), '%d/%m/%Y')))

>>> print most_recent
[['Abraham st.', ' 03/03/2011'], ['Moses rd.', ' 10/12/2013'], ['Smith St.', ' 01/01/1999']]
  

Предполагая, что input.csv содержит это:

 Address |Date
Abraham st.| 01/01/2008
Abraham st.| 02/02/2007
Abraham st.| 03/03/2011
Moses rd.| 10/12/2013
Moses rd.| 11/11/2011
Smith St.| 01/01/1999
  

Ответ №3:

Не уверен, что вам нужно «сравнивать с любой другой строкой» (но, возможно, я просто неправильно понимаю ваше намерение. Я бы просто сохранил самую новую строку, когда я перебираю столбец.

Что-то вроде этого псевдокода:

 saved_row = Null
for row in table:
    if not saved_row:
        saved_row = row
    else if row.date > saved_row.date:
        saved_row = row
  

Вероятно, существует более элегантный способ сохранить начальную строку в saved_row