2013-06-07 2 views
9

私は2つのキー列を持つパンダデータフレームを持っています。これらのキーのデカルト積がテーブルに存在していることを確認します。すべての組み合わせを含む2Dプロット)。私はこれを行うには、合理的に簡潔で慣用的な方法を思いついて問題を抱えています。キーのデカルト積がパンダテーブルに表示されるようにする

例えば、私は果物や野菜の組み合わせを与え、このテーブルで開始し、そしてそれらがどのように一緒に味:

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

私はすべての可能な組み合わせが発生したこのテーブルで終わるしたい:

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' 

I:

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 

は、ここで私はそれを行うことを見つけた最善の方法ですこれを行うには、よりシンプルでエラーが発生しにくい方法があるはずです...アドバイスはありますか?

誰かがどのように私は本当にインデックスでこれを行う方法についてを困惑していますので、マルチインデックスは、fruitveg列を含むとしてない場合の両方でこれを行うには私を見ることができれば、私は特にそれをいただければと思います。私のSQLの経験に基づいて、私はこれらがインデックスが意図している状況だと思います。

答えて

10

いつかこの回答の後に、私はcartesian_productをパンダに追加しました。MultiIndex.from_productが追加されました(another questionの提案に従う)。古い答えは次の

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 *を使用することができますこれは、より効率的である以下の簡素化を可能にしますreindexからMultiIndexによって:

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 

トリッキーな部分は右MultiInをつかむためにあります

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']) 

次に、あなただけのこれらのことにより、インデックスを再作成することができます:可能なすべての果物/野菜のDEXこの実装:

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が速くない場合は、十分なthis numpy implemention

注意を使用することを検討してくださいpandas.tools.util.cartesian_productで拡張されました。これにより、より多くのdtypeがサポートされます(そして、フードの中でMultiIndex.from_productで使用されています)。

+0

ありがとう、アンディ、これは私のためにうまくいきます。 'df1.reindex(fruit_x_veg、fill_value = 'UNKNOWN')'のようなreindexに 'fill_value'オプションの引数があるように見えます。 –

+0

@Dan Excellent!どのように素敵ですか? –

+1

@Dan FYIこの機能をネイティブに追加する方法については最近の[github issue](https://github.com/pydata/pandas/issues/3835)があります。 –

関連する問題