фильтр мультииндексированных сгруппированных pandas данных - PullRequest
1 голос
/ 07 апреля 2020

Данные выглядят следующим образом:

id  timestamp   date        value
1   2001-01-01  2001-05-01  0
1   2001-10-01  2001-05-01  1
2   2001-01-01  2001-05-01  0
2   2001-10-01  2001-05-01  0

, как вы видите, таблица содержит столбцы id, timestamp, date и value. Каждая строка с одинаковым id также имеет одинаковый date. Кроме того, date всегда по времени где-то между первым и последним timestamp каждого id.

Задача состоит в том, чтобы отфильтровать таблицу таким образом, чтобы удалить все id, который не содержит хотя бы одну запись с value > 0 во временной отметке после их индивидуального date.

Я реализовал это так, как я многоиндексировал таблицу с level 0 = id и level 1 = date и сортируйте это. Затем я группирую его по level 0. Затем я прохожу oop через каждую группу (id) и присваиваю новое значение, сообщающее мне, является ли id «хорошим» (логическим). Наконец, я фильтрую таблицу с хорошим значением True.

К сожалению, эта реализация медленная, как ад для большого (> 10M строк) набора данных. Я ищу способ ускорить это. Моя идея заключалась в использовании groupby.apply(lambda g: something), но я не смог заставить его работать, и я не знаю, является ли это самым быстрым из возможных вариантов.

Пример рабочего кода:

import pandas as pd

df = pd.DataFrame({'id': [1, 1, 2, 2],
                   'timestamp': ['01-01-2001', '01-10-2001', '01-01-2001', '01-10-2001'], 
                   'date': ['01-05-2001', '01-05-2001', '01-05-2001', '01-05-2001'],
                   'value': [0, 1, 0, 0]})                               

df['timestamp'] = pd.to_datetime(df['timestamp'])
df['date'] = pd.to_datetime(df['date'])
df = df.set_index(['id','timestamp']).sort_index()
grouped = df.groupby(level=0)
df['good'] = False
for i,(id,df_id) in enumerate(grouped):
    index = df_id.index
    df_id = df_id.droplevel(0)
    df.good.loc[index] = any(df_id.value.loc[df_id.date[0]:] > 0)
df = df[df.good == True]

1 Ответ

2 голосов
/ 07 апреля 2020

Для получения всех id с 1 в столбце value, а также timestamp выше, чем date, создайте 2 маски на Series.gt, цепочку на & для поразрядно AND и затем проверьте, если хотя бы один True на группу, GroupBy.any и GroupBy.transform:

df['timestamp'] = pd.to_datetime(df['timestamp'])
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values(['id','timestamp'])

m = df['value'].gt(0) & df['timestamp'].gt(df['date'])
df = df[m.groupby(df['id']).transform('any')]
print (df)
   id  timestamp       date  value
0   1 2001-01-01 2001-01-05      0
1   1 2001-01-10 2001-01-05      1
...