12

2 つのキー列を持つ Pandas データフレームがあり、それらのキーのデカルト積がテーブルに存在することを確認したいと考えています (すべての組み合わせを含む 2D プロットを作成する必要があるため)。これを行うための合理的に簡潔で慣用的な方法を思い付くのに苦労しています。

たとえば、果物と野菜の組み合わせと、それらがどのように一緒に味わうかを示す次の表から始めます。

   combo   fruit      veg
0  tasty   apple   carrot
1  yucky  banana   carrot
2  tasty  banana  lettuce
3  yucky   lemon  lettuce

考えられるすべての組み合わせが発生するこの表を完成させたいと思います。

    fruit      veg    combo
0   apple   carrot    tasty
1   apple  lettuce  UNKNOWN
2  banana   carrot    yucky
3  banana  lettuce    tasty
4   lemon   carrot  UNKNOWN
5   lemon  lettuce    yucky

これが私が見つけた最良の方法です:

import pandas as pd

# Initial data
df=pd.DataFrame(dict(fruit=['apple','banana','banana','lemon'],
                     veg=['carrot','carrot','lettuce','lettuce'],
                     combo=['tasty','yucky','tasty','yucky']))

# Solution starts here
veg=df.groupby('veg').size().reset_index()
fruit=df.groupby('fruit').size().reset_index()
fruit[0] = veg[0] = 0    #use this dummy column for the join to work!
cartesian = pd.merge(fruit, veg, how='outer', on=0)
del cartesian[0]
all_combos = pd.merge(cartesian, df, how='left')
all_combos[ pd.isnull(all_combos.combo) ] = 'UNKNOWN'

これを行うには、より簡単でエラーが発生しにくい方法が必要だと思います...何かアドバイスはありますか?

インデックスを使用してこれを行う方法について本当に困惑しているため、 fruitandveg列を含むマルチインデックスの有無にかかわらず、誰かがこれを行う方法を教えてくれれば特に感謝します。私の SQL の経験に基づいて、これらはまさにインデックスが意図されている状況だと思います。

4

1 に答える 1

13

この回答の後しばらくして、私cartesian_productはパンダに追加し、すぐに追加されました(別の質問MultiIndex.from_productでの提案に従って)。これにより、より効率的な次の単純化が可能になります。

In [21]: p = pd.MultiIndex.from_product(df1.index.levels, names=df1.index.names)

In [22]: df1.reindex(p, fill_value='UNKNOWN')
Out[22]:
                  combo
fruit  veg
apple  carrot     tasty
       lettuce  UNKNOWN
banana carrot     yucky
       lettuce    tasty
lemon  carrot   UNKNOWN
       lettuce    yucky

古い答えは次のとおりです。


果物と野菜をインデックスとして使用する場合、itertools.product* を使用して to を作成MultiIndexできますreindex

In [10]: from itertools import product

In [11]: df
Out[11]:
   combo   fruit      veg
0  tasty   apple   carrot
1  yucky  banana   carrot
2  tasty  banana  lettuce
3  yucky   lemon  lettuce

トリッキーな部分は、考えられるすべての果物/野菜の正しい MultiIndex を取得することです。

In [12]: fruit_x_veg = list(product(np.unique(df['fruit']), np.unique(df['veg'])))

In [13]: fruit_x_veg = pd.MultiIndex.from_tuples(fruit_x_veg,
                                                 names=['fruit', 'veg'])

次に、次の方法でインデックスを再作成できます。

In [14]: df1 = df.set_index(['fruit', 'veg'])

In [15]: df1
Out[15]:
                combo
fruit  veg
apple  carrot   tasty
banana carrot   yucky
       lettuce  tasty
lemon  lettuce  yucky

In [16]: df1.reindex(fruit_x_veg, fill_value='UNKNOWN')
Out[16]:
                  combo
fruit  veg
apple  carrot     tasty
       lettuce  UNKNOWN
banana carrot     yucky
       lettuce    tasty
lemon  carrot   UNKNOWN
       lettuce    yucky

*itertools.product十分に高速でない場合は、この numpy 実装の使用を検討してください

注: この実装は で拡張され、pandas.tools.util.cartesian_productより多くの dtype をサポートするようになりました (および の内部で使用されていMultiIndex.from_productます)。

于 2013-06-08T00:51:36.370 に答える