Эффективно сравнивайте каждую пару дат в двух столбцах в Python

У меня есть фрейм данных со столбцом дат начала и столбцом дат окончания. Я хочу проверить целостность дат, убедившись, что дата начала предшествует дате окончания (т.е. start_date ‹end_date). У меня есть более 14 000 наблюдений, которые нужно выполнить.

У меня есть данные в виде:

    Start       End
0   2008-10-01  2008-10-31  
1   2006-07-01  2006-12-31  
2   2000-05-01  2002-12-31  
3   1971-08-01  1973-12-31  
4   1969-01-01  1969-12-31  

Я добавил столбец для записи результата, хотя я просто хочу выделить, есть ли неправильные, чтобы я мог их удалить:

dates['Correct'] = " "

И начали проверять каждую пару дат, используя следующее, где мой фрейм данных называется датами:

for index, row in dates.iterrows():
    if dates.Start[index] < dates.End[index]:
        dates.Correct[index] = "correct"
    elif dates.Start[index] == dates.End[index]:
        dates.Correct[index] = "same"
    elif dates.Start[index] > dates.End[index]:
        dates.Correct[index] = "incorrect"

Что работает, это занимает очень много времени (около 15 минут). Мне нужен более эффективно работающий код - я что-то делаю не так или могу улучшить?


person emboylen    schedule 28.05.2016    source источник
comment
Удалите последний elif и замените его на else   -  person Deepanshu    schedule 28.05.2016


Ответы (3)


Почему бы просто не сделать это в векторизованном виде:

is_correct = dates['Start'] < dates['End']
is_incorrect = dates['Start'] > dates['End']
is_same = ~is_correct & ~is_incorrect
person aldanor    schedule 28.05.2016
comment
Спасибо! Так просто, так быстро! - person emboylen; 28.05.2016

Поскольку список не нужно сравнивать последовательно, вы можете повысить производительность, разделив набор данных, а затем используя несколько процессов для одновременного выполнения сравнения. Обратитесь за помощью к модулю многопроцессорности.

person anujm    schedule 28.05.2016

Что-то вроде следующего может быть быстрее:

import pandas as pd
import datetime

df = pd.DataFrame({
    'start': ["2008-10-01", "2006-07-01", "2000-05-01"],
    'end': ["2008-10-31", "2006-12-31", "2002-12-31"],
})


def comparison_check(df):
    start = datetime.datetime.strptime(df['start'], "%Y-%m-%d").date()
    end = datetime.datetime.strptime(df['end'], "%Y-%m-%d").date()
    if start < end:
        return "correct"
    elif start == end:
        return "same"
    return "incorrect"

In [23]: df.apply(comparison_check, axis=1)
Out[23]: 
0    correct
1    correct
2    correct
dtype: object

Время

In [26]: %timeit df.apply(comparison_check, axis=1)
1000 loops, best of 3: 447 µs per loop

Итак, по моим подсчетам, 14 000 строк должны занять (447/3) * 14 000 = (149 мкс) * 14 000 = 2,086 с, поэтому время может быть короче 15 минут :)

person Greg Lever    schedule 28.05.2016