Удаление выбросов на основе переменных столбца или мультииндекса во фрейме данных - PullRequest
1 голос
/ 29 мая 2020

Это еще один вопрос о выбросах IQR. У меня есть фрейм данных, который выглядит примерно так:

import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.randint(0,100,size=(100, 3)), columns=('red','yellow','green'))
df.loc[0:49,'Season'] = 'Spring'
df.loc[50:99,'Season'] = 'Fall'
df.loc[0:24,'Treatment'] = 'Placebo'
df.loc[25:49,'Treatment'] = 'Drug'
df.loc[50:74,'Treatment'] = 'Placebo'
df.loc[75:99,'Treatment'] = 'Drug'
df = df[['Season','Treatment','red','yellow','green']]
df

Я хотел бы найти и удалить выбросы для каждого условия (например, Spring Placebo, Spring Drug и т. Д. c). Не весь ряд, только ячейка. И хотел бы сделать это для каждого из «красных», «желтых», «зеленых» столбцов.

Есть ли способ сделать это, не разбивая фрейм данных на целую кучу подфреймов данных со всеми условиями, разбитыми по отдельности? Я не уверен, было бы легче, если бы «Сезон» и «Обработка» обрабатывались как столбцы или индексы. Я в порядке с любым способом.

Я пробовал кое-что с .ilo c и .lo c, но, похоже, не могу заставить его работать.

1 Ответ

1 голос
/ 29 мая 2020

Если необходимо заменить выбросы отсутствующими значениями, используйте GroupBy.transform на DataFrame.quantile, затем сравните меньшие и большие значения с помощью DataFrame.lt и DataFrame.gt, цепочка масок | для побитового OR и установка отсутствующих значений в DataFrame.mask, замена по умолчанию, поэтому не указано:

np.random.seed(2020)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 3)), columns=('red','yellow','green'))
df.loc[0:49,'Season'] = 'Spring'
df.loc[50:99,'Season'] = 'Fall'
df.loc[0:24,'Treatment'] = 'Placebo'
df.loc[25:49,'Treatment'] = 'Drug'
df.loc[50:74,'Treatment'] = 'Placebo'
df.loc[75:99,'Treatment'] = 'Drug'
df = df[['Season','Treatment','red','yellow','green']]

g = df.groupby(['Season','Treatment'])
df1 = g.transform('quantile', 0.05)
df2 = g.transform('quantile', 0.95)

c = df.columns.difference(['Season','Treatment'])
mask = df[c].lt(df1) | df[c].gt(df2)
df[c] = df[c].mask(mask)

print (df)
    Season Treatment   red  yellow  green
0   Spring   Placebo   NaN     NaN   67.0
1   Spring   Placebo  67.0    91.0    3.0
2   Spring   Placebo  71.0    56.0   29.0
3   Spring   Placebo  48.0    32.0   24.0
4   Spring   Placebo  74.0     9.0   51.0
..     ...       ...   ...     ...    ...
95    Fall      Drug  90.0    35.0   55.0
96    Fall      Drug  40.0    55.0   90.0
97    Fall      Drug   NaN    54.0    NaN
98    Fall      Drug  28.0    50.0   74.0
99    Fall      Drug   NaN    73.0   11.0

[100 rows x 5 columns]
...