Форум сайта python.su
Есть DataFrame с набором строк, в каждой строке есть столбец “Дата”. Необходимо найти строки даты которых различаются не больше чем на 5 дней.
Подскажите пожалуйста как это сделать?
Офлайн
Пример
>>> import datetime >>> t1 = datetime.datetime.now() >>> t1 datetime.datetime(2017, 6, 21, 17, 48, 43, 869203) >>> t2 = datetime.datetime.now() >>> (t2 - t1).total_seconds() 12.078282 >>> (t1 - t2).total_seconds() -12.078282 >>> >>> >>> abs((t1 - t2).total_seconds()) < 5 * 24 * 60 * 60 True
Офлайн
JOHN_16
примерно таким способ пользуюсь сейчас, но для этого приходиться пробегать по DataFrame с помощью питонячего цикла, а это медленно. Хочется реализовать нужное мне условие при помощи средств pandas, чтобы большие объемы данных быстро обрабатывались.
P.S работаю с файлами где бывает по миллиону записей, по этому есть требования по скорости работы скрипта.
Офлайн
df = pd.DataFrame(columns=['date']) df.date = [pd.Timestamp('2014-01-18'), pd.Timestamp('2014-01-22'), pd.Timestamp('2014-01-28'), pd.Timestamp('2014-02-19'), pd.Timestamp('2014-02-23')] df
date 0 2014-01-18 1 2014-01-22 2 2014-01-28 3 2014-02-19 4 2014-02-23
df['delta'] = df.date.diff().dt.days df
date delta 0 2014-01-18 NaN 1 2014-01-22 4.0 2 2014-01-28 6.0 3 2014-02-19 22.0 4 2014-02-23 4.0
df[df.delta <= 5]
date delta 1 2014-01-22 4.0 4 2014-02-23 4.0
Офлайн
Kurtz
import pandas as pd df = pd.DataFrame(columns=['sum_', 'date']) df.sum_ = [ 1, 1, 5, 7, 8, 9, 9, 45, 60 ] df.date = [ pd.Timestamp('2014-01-01'), pd.Timestamp('2014-01-02'), pd.Timestamp('2014-01-03'), pd.Timestamp('2014-01-04'), pd.Timestamp('2014-01-05'), pd.Timestamp('2014-01-22'), pd.Timestamp('2014-01-24'), pd.Timestamp('2014-01-25'), pd.Timestamp('2014-01-27') ] df['delta'] = df.date.diff().dt.days print(df)
Офлайн
jon34
Найти строки где sum_ одинаковое можно так:
df['sum_diff_neg'] = df['sum_'].shift(-1) == df['sum_'] df['sum_diff_pos'] = df['sum_'].shift(1) == df['sum_'] df['sum_diff_total'] = df['sum_diff_neg'] | df['sum_diff_pos'] df
sum_ date sum_diff_neg sum_diff_pos sum_diff_total 0 1 2014-01-01 True False True 1 1 2014-01-02 False True True 2 5 2014-01-03 False False False 3 7 2014-01-04 False False False 4 8 2014-01-05 False False False 5 9 2014-01-22 True False True 6 9 2014-01-24 False True True 7 45 2014-01-25 False False False 8 60 2014-01-27 False False False
Офлайн
Kurtz
Спасибо за помощь и желание помочь, но с поиском одинаковых сумм ни каких проблем нет проблемы, это уже сделано, проблема только с условием дат.
Офлайн
jon34
Не за что
Я возможно ошибаюсь, но проблема в том что в вашем примере все пары дат имеют разницу не больше пяти дней: 4 и 5 имеют разницу в 17 дней, но в тоже время 5 и 6 имеют разницу в 2 дня (мы сейчас говорим только о датах, не о sum_). Отсюда проблема, они все проходят условие <= 5. Можете привести другой пример, и как вы вы видите необходимый результат (опять же только даты, без sum_)?
Офлайн
Kurtz
Ну мне же надо обрабатывать реальные, боевые данные, а там даты могут быть какие угодно и надо получать разницу дат от строк где найденные одинаковые суммы, а не от минимальной даты.
Офлайн
jon34
Я изменил даты, посмотрите. Проблема в том что если мы говорим о парах дат, то нужно не менее трех различающихся дат, чтобы фильтр работал. Если отличаются только две последовательные даты, фильтр вернет True для всех.
import pandas as pd df = pd.DataFrame(columns=['sum_', 'date']) df.sum_ = [1, 1, 5, 7, 8, 9, 9, 45, 60] df.date = [pd.Timestamp('2014-01-01'), pd.Timestamp('2014-01-02'), pd.Timestamp('2014-01-03'), pd.Timestamp('2014-02-04'), pd.Timestamp('2014-02-05'), pd.Timestamp('2014-02-22'), pd.Timestamp('2014-03-24'), pd.Timestamp('2014-03-25'), pd.Timestamp('2014-04-27')] df
sum_ date 0 1 2014-01-01 1 1 2014-01-02 2 5 2014-01-03 3 7 2014-02-04 4 8 2014-02-05 5 9 2014-02-22 6 9 2014-03-24 7 45 2014-03-25 8 60 2014-04-27
df['date_diff_shift_pos'] = df['date'].diff(1).dt.days.apply(abs) <= 5 df.loc[0, 'date_diff_shift_pos'] = True # Из-за смещения вниз, первое значение всегда False df['date_diff_shift_neg'] = df['date'].diff(-1).dt.days.apply(abs) <= 5 df.loc[8, 'date_diff_shift_neg'] = True # Из-за смещения вверх, последнее значение всегда False df['date_diff_total'] = (df['date_diff_shift_neg'] == True) | (df['date_diff_shift_pos'] == True) df
sum_ date date_diff_shift_pos date_diff_shift_neg date_diff_total 0 1 2014-01-01 True True True 1 1 2014-01-02 True True True 2 5 2014-01-03 True False True 3 7 2014-02-04 False True True 4 8 2014-02-05 True False True 5 9 2014-02-22 False False False 6 9 2014-03-24 False True True 7 45 2014-03-25 True False True 8 60 2014-04-27 False True True
import pandas as pd df = pd.DataFrame(columns=['sum_', 'date']) df.sum_ = [1, 1, 5, 7, 8, 9, 9, 45, 60] df.date = [pd.Timestamp('2014-01-01'), pd.Timestamp('2014-01-02'), pd.Timestamp('2014-01-03'), pd.Timestamp('2014-01-04'), pd.Timestamp('2014-01-05'), pd.Timestamp('2014-01-22'), pd.Timestamp('2014-01-24'), pd.Timestamp('2014-01-25'), pd.Timestamp('2014-01-27')] df
sum_ date date_diff_shift_pos date_diff_shift_neg date_diff_total 0 1 2014-01-01 True True True 1 1 2014-01-02 True True True 2 5 2014-01-03 True True True 3 7 2014-01-04 True True True 4 8 2014-01-05 True False True 5 9 2014-01-22 False True True 6 9 2014-01-24 True True True 7 45 2014-01-25 True True True 8 60 2014-01-27 True True True
Отредактировано Kurtz (Июнь 28, 2017 09:54:10)
Офлайн