Идиоматическая очистка данных измерений из DataFrame с использованием квантиля - PullRequest
0 голосов
/ 22 июня 2019

У меня есть 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. Какое идиоматическое решение с учетом требуемой группировки
  2. Есть ли способ уменьшить влияние сильных выбросов, таких как 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))
...