Удалять ли пандану через группу? - PullRequest
2 голосов
/ 11 июня 2019

У меня есть простая функция, которая удаляет внешние элементы и возвращает новый DataFrame:

def remove_outliner(df):
   df.index = df.time
   df['median']= df['price'].rolling(15).median()
   df['std'] = df['price'].rolling(15).std()
   df["std+"] = df['median']+3*df['std']
   df["std-"] = df['median']-3*df['std']
   #filter setup
   df2 = df[(df.price <= df['median']+3*df['std']) &
            (df.price >= df['median']-3*df['std'])]
   return df2

Есть ли способ применить такую ​​функцию с помощью groupby?Итак, что-то вроде этого (псевдокод):

df.groupby(["product"]).filter(remove_outliner).concat_groups()

Мой наивный подход заключается в переборе групп.Сохраните их в списке, а затем примените pd.concat.Но я надеюсь, что есть более элегантный способ.Большое спасибо за любую подсказку!

PS: Пример ввода

                               product price 
          2014-08-25 01:00:00  A       1.2
          2014-08-25 02:00:00  B       7.2
          2014-08-25 03:00:00  A       1.2
          2014-08-25 04:00:00  B       7.2
          2014-08-25 04:00:00  A       1.2
          2014-08-25 05:00:00  A       99.2
          2014-08-25 06:00:00  A       1.2
          2014-08-25 06:00:00  B       7.2
          2014-08-25 21:00:00  A       1.2
          2014-08-25 22:00:00  B       88.2

Ожидаемый результат

                               product price 
          2014-08-25 01:00:00  A       1.2
          2014-08-25 02:00:00  B       7.2
          2014-08-25 03:00:00  A       1.2
          2014-08-25 04:00:00  B       7.2
          2014-08-25 04:00:00  A       1.2
          2014-08-25 06:00:00  A       1.2
          2014-08-25 06:00:00  B       7.2
          2014-08-25 21:00:00  A       1.2

Если первые строки исчезнут, это будет хорошо.Функция remove_outliner добавляет несколько столбцов, но их можно удалить.Поскольку разные продукты могут иметь разную шкалу цен, я не могу применить фильтр только к цене, и мне нужно работать с группами.

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Поэтому я попытался немного изменить вашу функцию (вы, вероятно, не хотите median и std в вашем фрейме данных):

def remove_outliner(df):
    roll_median= df['price'].rolling(15).median()
    roll_std = df['price'].rolling(15).std()

    #filter setup
    df2 = df[(df.price.le(roll_median + 3*roll_std) &
            (df.price.ge(roll_median - 3*roll_std)]

    return df2

# set_index here, not inside the function:
df.set_index('time').groupby('product', group_keys=False).apply(remove_outliner)
1 голос
/ 11 июня 2019

Попробуйте:

df_wo_outliers = df[~((df < (Q1 - 1.5 * IQR)) |(df > (Q3 + 1.5 * IQR))).any(axis=1)]

Есть также хорошая статья, в которой рассказывается о обнаружении и обработке выбросов .

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...