Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 21, 2017 12:43:41

jon34
Зарегистрирован: 2016-02-14
Сообщения: 47
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

Есть DataFrame с набором строк, в каждой строке есть столбец “Дата”. Необходимо найти строки даты которых различаются не больше чем на 5 дней.
Подскажите пожалуйста как это сделать?

Офлайн

#2 Июнь 21, 2017 17:50:17

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Pandas сравнение дат

Пример

 >>> 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



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

#3 Июнь 21, 2017 20:44:57

jon34
Зарегистрирован: 2016-02-14
Сообщения: 47
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

JOHN_16
примерно таким способ пользуюсь сейчас, но для этого приходиться пробегать по DataFrame с помощью питонячего цикла, а это медленно. Хочется реализовать нужное мне условие при помощи средств pandas, чтобы большие объемы данных быстро обрабатывались.

P.S работаю с файлами где бывает по миллиону записей, по этому есть требования по скорости работы скрипта.

Офлайн

#4 Июнь 23, 2017 13:25:03

Kurtz
Зарегистрирован: 2016-03-18
Сообщения: 35
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

 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

Офлайн

#5 Июнь 26, 2017 07:59:22

jon34
Зарегистрирован: 2016-02-14
Сообщения: 47
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

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)
На цифрах не выходит логика, которая мне нужна. Мне нужно найти строки, где sum_ одинаковое и где разница между датами не больше 5 дней. То есть должны выбираться строки 0, 1, 5, 6.

Офлайн

#6 Июнь 27, 2017 09:26:40

Kurtz
Зарегистрирован: 2016-03-18
Сообщения: 35
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

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
Наверное что-то подобное можно сделать и с датами.

Офлайн

#7 Июнь 27, 2017 11:50:11

jon34
Зарегистрирован: 2016-02-14
Сообщения: 47
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

Kurtz
Спасибо за помощь и желание помочь, но с поиском одинаковых сумм ни каких проблем нет проблемы, это уже сделано, проблема только с условием дат.

Офлайн

#8 Июнь 27, 2017 16:31:46

Kurtz
Зарегистрирован: 2016-03-18
Сообщения: 35
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

jon34
Не за что
Я возможно ошибаюсь, но проблема в том что в вашем примере все пары дат имеют разницу не больше пяти дней: 4 и 5 имеют разницу в 17 дней, но в тоже время 5 и 6 имеют разницу в 2 дня (мы сейчас говорим только о датах, не о sum_). Отсюда проблема, они все проходят условие <= 5. Можете привести другой пример, и как вы вы видите необходимый результат (опять же только даты, без sum_)?

Офлайн

#9 Июнь 28, 2017 07:12:05

jon34
Зарегистрирован: 2016-02-14
Сообщения: 47
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

Kurtz
Ну мне же надо обрабатывать реальные, боевые данные, а там даты могут быть какие угодно и надо получать разницу дат от строк где найденные одинаковые суммы, а не от минимальной даты.

Офлайн

#10 Июнь 28, 2017 09:49:15

Kurtz
Зарегистрирован: 2016-03-18
Сообщения: 35
Репутация: +  0  -
Профиль   Отправить e-mail  

Pandas сравнение дат

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
В этом случае отфильтровалась только одна дата (date_diff_total == False), так как она отличается от всех двух соседних. Далее вы можете применить фильтр по суммам, но в случае с вашими первоначальными данными сработает только он, так как, фильтр по датам вернет все.
 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)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version