Создать столбец выбросов в группе панд данных в DataFrame - PullRequest
0 голосов
/ 25 мая 2018

У меня есть очень большой пандан DataFrame с несколькими тысячами кодов и стоимостью, связанной с каждым из них (пример):

data = {'code': ['a', 'b', 'a', 'c', 'c', 'c', 'c'],
        'cost': [10, 20, 100, 10, 10, 500, 10]}
df = pd.DataFrame(data)

Я создаю groupby объект на уровне code, т. е.:

grouped = df.groupby('code')['cost'].agg(['sum', 'mean']).apply(pd.Series)

Теперь мне действительно нужно добавить новый столбец в этот grouped DataFrame, определяющий процент кодов, которые имеют затраты на выбросы.Мой первоначальный подход был такой внешней функцией (используя iqr из scipy):

def is_outlier(s):
    # Only calculate outliers when we have more than 100 observations
    if s.count() >= 100:
        return np.where(s >= s.quantile(0.75) + 1.5 * iqr(s), 1, 0).mean()
    else:
        return np.nan

Написав эту функцию, я добавил is_outlier к своим agg аргументам в groupby выше.Это не сработало, потому что я пытаюсь оценить этот коэффициент is_outlier для каждого элемента в серии cost:

grouped = df.groupby('code')['cost'].agg(['sum', 'mean', is_outlier]).apply(pd.Series)

Я пытался использовать pd.Series.where, но он не имеет такой же функциональностикак np.where.Есть ли способ изменить мою функцию is_outlier, которая должна принимать ряд cost в качестве аргумента, чтобы правильно оценить уровень выбросов для каждого кода?Или я совершенно не в курсе?

ОБНОВЛЕНИЕ Желаемый результат (минус минимальное требование к наблюдениям для этого примера):

>>> grouped

  code    sum    mean    is_outlier

0  'a'    110     55     0.5
1  'b'    20      20     0
2  'c'    530     132.5  0.25

Примечание: мой образец ужасен вдля меня, чтобы рассчитать выбросы, так как у меня есть 2, 1 и 4 наблюдения соответственно для каждого code.В производственном фрейме данных каждый код имеет сотни или тысячи наблюдений, каждое из которых связано со стоимостью.В приведенном выше примере выборки значения для is_outlier означают, что для 'a' одно из двух наблюдений имеет стоимость в диапазоне выбросов, для 'c' одно из четырех наблюдений имеет стоимость в диапазоне выбросови т. д. - я пытаюсь воссоздать это в своей функции, присваивая 1 и 0 в результате np.where() и получая .mean() из этого

.apply(pd.Series), необходимого для приведения <pandas.core.groupby.SeriesGroupBy object> resulting from groupby into a DataFrame. s is a pandas Series with all values of стоимость for each код , as generated from the groupby operation ( split phase of split-apply-Объединить`)

1 Ответ

0 голосов
/ 25 мая 2018

Используемые данные

# Loading Libraries
import pandas as pd;
import numpy as np;

# Creating Data set
data = {'code': ['a', 'b', 'a', 'c', 'c', 'c', 'c', 'a', 'a', 'a'],
    'cost': [10, 20, 200, 10, 10, 500, 10, 10, 10, 10]}

df = pd.DataFrame(data)

Определение функции для расчета доли выбросов в указанном столбце

def outlier_prop(df,name,group_by):

    """
    @Packages required
    import pandas as pd;
    import numpy as np;

    @input
    df = original dataframe
    name = This is the name column for which you want the dummy list
    group_by = column to group by

    @output
    data frame with an added column 'outlier' containing the proportion of outliers
    """

    # Step 1: Create a dict of values for each group
    value_dict = dict()
    for index,i in enumerate(df[group_by]):
        if i not in value_dict.keys():
            value_dict[i] = [df[name][index]]
        else:
            value_dict[i].append(df[name][index])

    # Step 2: Calculate the outlier value for each group and store as a dict
    outlier_thres_dict = dict()
    unique_groups = set(df[group_by])
    for i in unique_groups:
        outlier_threshold = np.mean(value_dict[i]) + 1.5*np.std(value_dict[i])
        outlier_thres_dict[i] = outlier_threshold

    # Step 3: Create a list indicating values greater than the group specific threshold
    dummy_list = []
    for index,i in enumerate(df[group_by]):
        if df[name][index] > outlier_thres_dict[i]:
            dummy_list.append(1)
        else:
            dummy_list.append(0)

    # Step 4: Add the list to the original dataframe
    df['outlier'] = dummy_list

    # Step 5: Grouping and getting the proportion of outliers
    grouped = df.groupby(group_by).agg(['sum', 'mean']).apply(pd.Series)

    # Step 6: Return data frame
    return grouped

Вызов функции

outlier_prop(df, 'cost', 'code')

Выход

https://raw.githubusercontent.com/magoavi/stackoverflow/master/50533570.png

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