11

1 つの列に numpy 配列が含まれている pandas DataFrame を使用しています。集計によってその列を合計しようとすると、「集計値を生成する必要があります」というエラーが表示されます。

例えば

import pandas as pd
import numpy as np

DF = pd.DataFrame([[1,np.array([10,20,30])],
               [1,np.array([40,50,60])], 
               [2,np.array([20,30,40])],], columns=['category','arraydata'])

これは私が期待するように動作します:

DF.groupby('category').agg(sum)

出力:

             arraydata
category 1   [50 70 90]
         2   [20 30 40]

ただし、実際のデータ フレームには複数の数値列があるため、arraydata は集計対象の既定の列として選択されておらず、手動で選択する必要があります。これが私が試した1つのアプローチです:

g=DF.groupby('category')
g.agg({'arraydata':sum})

ここに別のものがあります:

g=DF.groupby('category')
g['arraydata'].agg(sum)

どちらも同じ出力が得られます。

Exception: must produce aggregated value

ただし、配列データではなく数値を使用する列がある場合は、正常に機能します。これを回避することはできますが、紛らわしく、これがバグなのか、それとも何か間違っているのか疑問に思っています。ここで配列を使用するのはちょっと特殊なケースかもしれませんし、実際にそれらがサポートされているかどうかはわかりませんでした。アイデア?

ありがとう

4

3 に答える 3

15

おそらくもっと厄介な方法の 1 つは、GroupByオブジェクトを反復処理することです (タプルを生成し(grouping_value, df_subgroup)ます。たとえば、ここで目的を達成するには、次のようにします。

grouped = DF.groupby("category")
aggregate = list((k, v["arraydata"].sum()) for k, v in grouped)
new_df = pd.DataFrame(aggregate, columns=["category", "arraydata"]).set_index("category")

とにかく、これは pandas がボンネットの下で行っていることと非常に似ている [groupby、次にいくつかの集約を行い、次にマージする] ため、実際には多くのことを失うことはありません。


内部に飛び込む

ここでの問題は、エラーが発生した場所からこのスニペットでわかるように、pandas が配列をインテリジェントに再形成したいため、出力が ではないことを明示的にチェックしていることです。ndarray_aggregate_named

def _aggregate_named(self, func, *args, **kwargs):
    result = {}

    for name, group in self:
        group.name = name
        output = func(group, *args, **kwargs)
        if isinstance(output, np.ndarray):
            raise Exception('Must produce aggregated value')
        result[name] = self._try_cast(output, group)

    return result

私の推測ではgroupby、同じインデックスを使用して DataFrame をインテリジェントに元に戻そうとするように明示的に設定されており、すべてが適切に調整されているため、これが発生すると考えられます。そのような DataFrame にネストされた配列があることはめったにないため、ndarrays をチェックして、実際に集計関数を使用していることを確認します。私の直感では、これは の仕事のように感じPanelますが、完全に変換する方法がわかりません。余談ですが、次のように出力をリストに変換することで、この問題を回避できます。

DF.groupby("category").agg({"arraydata": lambda x: list(x.sum())})

これで Python オブジェクトの配列ができたので、Pandas は文句を言いません。[しかし、これは実際には型チェックをごまかすだけです]。また、配列に戻したい場合は、配列に適用np.arrayするだけです。

result = DF.groupby("category").agg({"arraydata": lambda x: list(x.sum())})
result["arraydata"] = result["arraydata"].apply(np.array)

この問題をどのように解決したいかは、列がある理由ndarrayと、同時に他のものを集計するかどうかによって異なります。GroupByとはいえ、上で示したように、いつでも反復できます。

于 2013-06-07T03:04:02.903 に答える
2

これを行わないと、パンダははるかに効率的に機能します(たとえば、数値データを使用するなど)。もう 1 つの方法は、この種の多次元データにPanelオブジェクトを使用することです。

これはバグのように見えますが、結果が配列であるため、純粋に例外が発生しています。

Exception: Must produce aggregated value

In [11]: %debug
> /Users/234BroadWalk/pandas/pandas/core/groupby.py(1511)_aggregate_named()
   1510             if isinstance(output, np.ndarray):
-> 1511                 raise Exception('Must produce aggregated value')
   1512             result[name] = self._try_cast(output, group)

ipdb> output
array([50, 70, 90])

ソース コードからこれらの 2 行をむやみに削除しても、期待どおりに動作します。

In [99]: g.agg(sum)
Out[99]:
             arraydata
category
1         [50, 70, 90]
2         [20, 30, 40]

注: 何らかの理由でそこにいることはほぼ確実です...

于 2013-06-07T03:02:15.020 に答える