удалить строку, если она соответствует заданному условию при выполнении iterrows - PullRequest
0 голосов
/ 25 мая 2018

У меня есть кадр данных pandas, отсортированный по id, date1 и столбцам id, date1, date2, date3 (три разные даты трех разных событий).

Я хочу перебрать каждую строку и удалитьстрока, если разница в днях для двух дат1 записей одного и того же идентификатора (две разные записи одного и того же идентификатора) составляет> 10, то же самое для дат2 и то же для дат3.

Я думал сделать это с помощьюfor loop и временный словарь для хранения каждого идентификатора и его дат, но он довольно неэффективен с точки зрения O (время) и, более того, O (хранилище).

Это то, что я имею в виду:

Допустим, это пример фрейма данных

e = pd.DataFrame({
    'id':[1,1,1,
          1,2,2,
          2],
    'date1':[datetime.date(2018,10,1),datetime.date(2018,10,1),datetime.date(2018,9,29),
             datetime.date(2010,3,4),datetime.date(2018,12,10),datetime.date(2018,12,4),
             datetime.date(2018,11,29)],
    'date2':[datetime.date(2018,10,3),datetime.date(2018,10,3),datetime.date(2018,9,29),
             datetime.date(2018,9,25),datetime.date(2018,12,10),datetime.date(2018,12,4),
             datetime.date(2015,1,1)],
    'date3':[datetime.date(2018,10,1),datetime.date(2018,10,1),datetime.date(2018,9,27),
             datetime.date(2018,9,23),datetime.date(2018,12,10),datetime.date(2018,12,3),
             datetime.date(2015,1,1)]})

Затем я удалил бы нежелательные строки на основе предыдущего описания с этим кодом.

e_dict = {}
for index, row in e.iterrows():
    id = row['id']
if id in e_dict:
    date1_diff = abs((row['date1']-e_dict[id][-1]['date1']).days)
    #print(date1_diff)
    date2_diff = abs((row['date2']-ff_dict[api10][-1]['date2']).days)
    #print(job_end_date_diff)
    date3_diff = abs((row['date3']-ff_dict[api10][-1]['date3']).days)
    #print(date3_diff)
    #print('new row')
    if date1_diff <= 10 and date2_diff <= 10 and date3_diff <= 10:
        # drop current row from df
    if id in e_dict:
        e_dict.append(id)
    else:
        e_dict[id] = [row]

И желаемый результат,то есть, новый вывод будет:

e = pd.DataFrame({
    'id':[1,
          1,2,
          2],
    'date1':[datetime.date(2018,10,1),
             datetime.date(2010,3,4),datetime.date(2018,12,10),
             datetime.date(2018,11,29)],
    'date2':[datetime.date(2018,10,3),
             datetime.date(2018,9,25),datetime.date(2018,12,10),
             datetime.date(2015,1,1)],
    'date3':[datetime.date(2018,10,1),
             datetime.date(2018,9,23),datetime.date(2018,12,10),
             datetime.date(2015,1,1)]})

1 Ответ

0 голосов
/ 25 мая 2018

Используя сдвиг для каждого ряда данных, вы можете использовать его для фильтрации.

def diff_zero(ds):
    diff = (ds.shift() - ds).apply(lambda y: y)
    return ~pd.isna(diff) | (diff == 0.0)

def days_diff_less_than(ds, val):
    diff = (ds.shift() - ds).apply(lambda y: y.days).abs()
    return pd.isna(diff) | (diff <= val)

e = e.drop(e[days_diff_less_than(e['dates1'], 10) & diff_zero(e['id'])].index)
e = e.drop(e[days_diff_less_than(e['dates2'], 10) & diff_zero(e['id'])].index)
e = e.drop(e[days_diff_less_than(e['dates3'], 10) & diff_zero(e['id'])].index)

print(e)

#    id      dates1      dates2      dates3
# 0   1  2018-10-01  2018-10-01  2018-10-01
# 3   1  2010-03-04  2010-03-04  2010-03-04
# 4   2  2018-12-10  2018-12-10  2018-12-10
# 6   2  2015-01-01  2015-01-01  2015-01-01

Если вместо этого вся разница в днях должна быть меньше 10, код изменится на:

e = e.drop(
    e[days_diff_less_than(e['date1'], 10) & days_diff_less_than(e['date2'], 10) & days_diff_less_than(e['date3'], 10) & diff_zero(e['id'])].index
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...