91

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 ...
4

8 に答える 8

113

はい; .apply(...)各サブで呼び出される関数を使用しますDataFrame。例えば:

grouped = df.groupby(keys)

def wavg(group):
    d = group['data']
    w = group['weights']
    return (d * w).sum() / w.sum()

grouped.apply(wavg)
于 2012-06-09T22:07:32.317 に答える
5

私はこれを頻繁に行っており、次のものが非常に便利であることがわかりました。

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非数値列が削除されます。

于 2016-02-10T23:07:57.237 に答える
4

これを達成すること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 (e.g. 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
于 2016-02-19T18:51:17.720 に答える