Функция агрегации Pandas DataFrame с использованием нескольких столбцов

Есть ли способ написать функцию агрегации, которая используется в методе DataFrame.agg , который будет иметь доступ к нескольким столбцам данных, которые агрегируются? Типичными примерами использования могут быть взвешенные средние взвешенные стандартные отклонения.

Я хотел бы написать что-то вроде

 def wAvg(c, w): return ((c * w).sum() / w.sum()) df = DataFrame(....) # df has columns c and w, i want weighted average # of c using w as weight. df.aggregate ({"c": wAvg}) # and somehow tell it to use w column as weights ... 

5 Solutions collect form web for “Функция агрегации Pandas DataFrame с использованием нескольких столбцов”

Да; используйте .apply(...) , которая будет вызываться на каждом суб- DataFrame . Например:

 grouped = df.groupby(keys) def wavg(group): d = group['data'] w = group['weights'] return (d * w).sum() / w.sum() grouped.apply(wavg) 

Следующее (на основе ответа Wes McKinney) выполняет именно то, что я искал. Я был бы рад узнать, есть ли более простой способ сделать это в pandas .

 def wavg_func(datacol, weightscol): def wavg(group): dd = group[datacol] ww = group[weightscol] * 1.0 return (dd * ww).sum() / ww.sum() return wavg def df_wavg(df, groupbycol, weightscol): grouped = df.groupby(groupbycol) df_ret = grouped.agg({weightscol:sum}) datacols = [cc for cc in df.columns if cc not in [groupbycol, weightscol]] for dcol in datacols: try: wavg_f = wavg_func(dcol, weightscol) df_ret[dcol] = grouped.apply(wavg_f) except TypeError: # handle non-numeric columns df_ret[dcol] = grouped.agg({dcol:min}) return df_ret 

Функция df_wavg() возвращает фрейм данных, сгруппированный столбцом «groupby», и возвращает сумму весов для столбца весов. Другими столбцами являются либо взвешенные средние значения, либо, если они не являются числовыми, для агрегирования используется функция min() .

Я делаю это много и нашел следующее достаточно удобным:

 def weighed_average(grp): return grp._get_numeric_data().multiply(grp['COUNT'], axis=0).sum()/grp['COUNT'].sum() df.groupby('SOME_COL').apply(weighed_average) 

Это вычислит средневзвешенное значение всех числовых столбцов в df и уменьшит числовые.

Выполнение этого с помощью groupby(...).apply(...) не выполняется. Вот решение, которое я использую все время (по существу используя логику Калу).

 def grouped_weighted_average(self, values, weights, *groupby_args, **groupby_kwargs): """ :param values: column(s) to take the average of :param weights_col: column to weight on :param group_args: args to pass into groupby (eg the level you want to group on) :param group_kwargs: kwargs to pass into groupby :return: pandas.Series or pandas.DataFrame """ if isinstance(values, str): values = [values] ss = [] for value_col in values: df = self.copy() prod_name = 'prod_{v}_{w}'.format(v=value_col, w=weights) weights_name = 'weights_{w}'.format(w=weights) df[prod_name] = df[value_col] * df[weights] df[weights_name] = df[weights].where(~df[prod_name].isnull()) df = df.groupby(*groupby_args, **groupby_kwargs).sum() s = df[prod_name] / df[weights_name] s.name = value_col ss.append(s) df = pd.concat(ss, axis=1) if len(ss) > 1 else ss[0] return df pandas.DataFrame.grouped_weighted_average = grouped_weighted_average 

Мое решение похоже на решение Натаниэля, только для одного столбца, и я не делаю глубокое копирование всего кадра данных каждый раз, что может быть непомерно медленным. Увеличение производительности по группе решений (…). Apply (…) составляет около 100x (!)

 def weighted_average(df,data_col,weight_col,by_col): df['_data_times_weight'] = df[data_col]*df[weight_col] df['_weight_where_notnull'] = df[weight_col]*pd.notnull(df[data_col]) g = df.groupby(by_col) result = g['_data_times_weight'].sum() / g['_weight_where_notnull'].sum() del df['_data_times_weight'], df['_weight_where_notnull'] return result 
  • pandas - добавить новый столбец в dataframe из словаря
  • Трудный импорт .dat-файла
  • Pandas записывает данные в другую схему postgresql
  • Как отсортировать регистр строк без учета регистра в Pandas DataFrame
  • откройте выбранные строки с помощью pandas, используя «chunksize» и / или «iterator»,
  • Преобразование группы pandas по объекту в мультииндексированный Dataframe
  • pandas concat ignore_index не работает
  • Фильтрация данных в пандах: используйте список условий
  •  
    Interesting Posts for Van-Lav

    как преобразовать список dict в dict

    Как сопоставить текстовый узел, затем следуйте за родительскими узлами, используя XPath

    используя python для разбора двоеточия (:) разделили строку на объект

    Отображение диаграммы networkx с метками

    Как мне получить путь к скрипту Python, в котором я запущен?

    Как вы обновляете уровни pandas MultiIndex после разрезания его DataFrame?

    Используя подпроцесс Python и Popen в одном скрипте для запуска другого скрипта Python, который требует взаимодействия с пользователем (по raw_input)

    Тестирование модулей Python: автоматический запуск отладчика при неудачном тестировании

    Как отображать объекты InLine в интерфейсе администратора Django

    Python: как проверить, содержит ли строка в юникоде одинарный символ?

    Как уменьшить размер файла изображения с помощью PIL

    Python: SQLAlchemy ImportError: нет модуля с именем pysqlite2

    Почему я получаю следующую ошибку в Python «ImportError: Нет модуля с именем py»?

    Есть ли способ прозрачно выполнить проверку на объектах SQLAlchemy?

    Лучший способ запуска удаленных команд через ssh в Twisted?

    Python - лучший язык программирования в мире.