У меня есть DataFrame, содержащий информацию о силе сигнала в разных местах.Я пытаюсь очистить эти данные от выбросов, но из-за разных мест я не могу использовать среднее значение или квантиль для всего набора данных.
У меня есть проверочное число мест, включая Идиоматический клип на квантиле дляDataFrame или нормализация квантилей на пандах. Dataframe , но ни один не обеспечивает хорошего идиоматического решения, особенно для новичков в Pandas ...
Я достиг чего-то подобного ниже, но это кажется ужасным, особенно дляпроизводительность и сложность ...
df = pd.DataFrame({'x': {'A': 0, "A'": 0, "A''": 0, 'B': 0, "B'": 0},
'y': {'A': 0, "A'": 0, "A''": 0, 'B': 1, "B'": 1},
'signal': {'A': 'a', "A'": 'a', "A''": 'a', 'B': 'a', "B'": 'b'},
'measure': {'A': .5, "A'": 1, "A''": 0.55, 'B': .8, "B'": 0.78}})
def remove_outliers(data, width=0.8):
lower = .5 - width/2
upper = .5 + width/2
data = data.copy(deep=True)
restructured_data = data.groupby(['x', 'y', 'signal'])
reliable_measure = restructured_data.quantile([lower, upper])
print(reliable_measure)
#TODO: Pandas way
data['is_reliable_measure'] = False
for ind in data.index:
x = data['x'][ind]
y = data['y'][ind]
signal = data['signal'][ind]
measure = data['measure'][ind]
l_group = (x, y, signal, lower)
u_group = (x, y, signal, upper)
l = reliable_measure.loc[l_group][0]
u = reliable_measure.loc[u_group][0]
is_reliable_measure = (l <= measure <= u)
data.loc[ind, 'is_reliable_measure'] = is_reliable_measure
return data # [data['is_reliable_measure']]
print (remove_outliers(df))
Результат более или менее правильный, так как позволяет убрать выбросы:
# Quantile +- 0.4
measure
x y signal
0 0 a 0.1 0.51
0.9 0.91
1 a 0.1 0.80
0.9 0.80
b 0.1 0.78
0.9 0.78
Вывод функции:
x y signal measure is_reliable_measure
A 0 0 a 0.50 False
A' 0 0 a 1.00 False
A'' 0 0 a 0.55 True
B 0 1 a 0.80 True
B' 0 1 b 0.78 True
Итак, мыможет наблюдать правильное удаление:
- x: 0, y: 0, сигнал: a, мера: 1
- x: 0, y: 0, сигнал: a, мера:0,5
Вопросы:
- Какое идиоматическое решение с учетом требуемой группировки
- Есть ли способ уменьшить влияние сильных выбросов, таких как 1 впример выше, который потенциально может привести кнг вполне правильно 0,5 (0,5 и 0,55 близко ...)?
PS
Я считаю, что код может быть что-то вроде:
df[ df.isin(
df.groupby(['x', 'y', 'signal']).quantile([lower, upper])
)]
все еще нетконечно, как этого добиться.
Следуя предложению @ juanpa.arrivillaga, мы имеем:
df = pd.DataFrame({'x': {'A': 0, "A'": 0, "A''": 0, 'B': 0, "B'": 0},
'y': {'A': 0, "A'": 0, "A''": 0, 'B': 1, "B'": 1},
'signal': {'A': 'a', "A'": 'a', "A''": 'a', 'B': 'a', "B'": 'b'},
'measure': {'A': .5, "A'": 1, "A''": 0.55, 'B': .8, "B'": 0.78}})
def remove_outliers(data, width=0.8):
lower = .5 - width/2
upper = .5 + width/2
data = data.copy(deep=True)
restructured_data = data.groupby(['x', 'y', 'signal'])
reliable_measure = restructured_data.quantile([lower, upper])
print(reliable_measure)
#TODO: Pandas way
data['is_reliable_measure'] = False
for ind, x, y, signal, measure, _ in data.itertuples():
l_group = (x, y, signal, lower)
u_group = (x, y, signal, upper)
l = reliable_measure.loc[l_group][0]
u = reliable_measure.loc[u_group][0]
is_reliable_measure = (l <= measure <= u)
data.loc[ind, 'is_reliable_measure'] = is_reliable_measure
return data # [data['is_reliable_measure']]
print (remove_outliers(df))