2016-03-24 6 views
1

私は2つのDataFrameを持っていますが、1つは「レシピ」、成分の組み合わせ、もう1つは「好き」です。組み合わせは「のような」に記載されている場合python pandas.Dataframeのリストに従ってラベルを割り当てる方法は?

recipe = pd.DataFrame({'A': ['chicken','beef','pork','egg', 'chicken', 'egg', 'beef'], 
         'B': ['sweet', 'hot', 'salty', 'hot', 'sweet', 'salty', 'hot']}) 
recipe 
    A  B 
0 chicken sweet 
1  beef hot 
2  pork salty 
3  egg hot 
4 chicken sweet 
5  egg salty 
6  beef hot 

like = pd.DataFrame({'A':['beef', 'egg'], 'B':['hot', 'salty']}) 
like 
    A  B 
0 beef hot 
1 egg salty 

私は、レシピに列「C」を追加することができますどのように、私はそれに値を「はい」、そうでない場合は「いいえ」を与えますか?

私が望む結果は、問題は私の両方のデータフレームが大きいです

recipe 
     A  B C 
0 chicken sweet no 
1  beef hot yes 
2  pork salty no 
3  egg hot no 
4 chicken sweet no 
5  egg salty yes 
6  beef hot yes 

です。私は手動で '好き'の項目を選択して 'レシピ'に 'はい'のラベルを割り当てることはできません。それを行う簡単な方法はありますか?

+0

「A」の項目は「牛」ですが、「B」の「塩味」はミスマッチの原因になりますか? – Leb

+0

@Leb、 'A'が' beef'、 'B'が' salty'ならば、私は 'no'というラベルを割り当てます。不一致は起こりません。 – xirururu

答えて

2

あなたはmergenumpy.whereを使用することができます。

df = pd.merge(recipe, like, on=['A','B'], indicator=True, how='left') 
print df 
     A  B  _merge 
0 chicken sweet left_only 
1  beef hot  both 
2  pork salty left_only 
3  egg hot left_only 
4 chicken sweet left_only 
5  egg salty  both 
6  beef hot  both 

df['C'] = np.where(df['_merge'] == 'both', 'yes', 'no') 

print df[['A','B','C']] 
     A  B C 
0 chicken sweet no 
1  beef hot yes 
2  pork salty no 
3  egg hot no 
4 chicken sweet no 
5  egg salty yes 
6  beef hot yes 

高速化df['_merge'] == 'both'を使用している:

In [460]: %timeit np.where(np.in1d(df['_merge'],'both'), 'yes', 'no') 
100 loops, best of 3: 2.22 ms per loop 

In [461]: %timeit np.where(df['_merge'] == 'both', 'yes', 'no') 
1000 loops, best of 3: 652 µs per loop 
+0

ありがとうございます!私はいつも 'concat'と 'join'について考える。しかし、解決策を見つけることができませんでした。 「マージ」が答えです。:D – xirururu

1

あなたはlike'yes'秒のC列を追加し、likerecipeをマージすることができます。 一致する行は、列にyesとなります。一致しない行は、NaNとなります。その後、'no'秒でNaNを置き換えるためにfillnaを使用することができます。あなたのようなABの両方を照合することによってset_valueを使用することができます

import pandas as pd 
recipe = pd.DataFrame({'A': ['chicken','beef','pork','egg', 'chicken', 'egg', 'beef'], 
         'B': ['sweet', 'hot', 'salty', 'hot', 'sweet', 'salty', 'hot']}) 

like = pd.DataFrame({'A':['beef', 'egg'], 'B':['hot', 'salty']}) 
like['C'] = 'yes' 
result = pd.merge(recipe, like, how='left').fillna('no') 
print(result) 

利回り

  A  B C 
0 chicken sweet no 
1  beef hot yes 
2  pork salty no 
3  egg hot no 
4 chicken sweet no 
5  egg salty yes 
6  beef hot yes 
1

:意志

recipe.set_value(recipe[recipe.A.isin(like.A) & recipe.B.isin(like.B)].index,'C','yes') 
recipe.fillna('no') 

をあなたに与える:

  A  B C 
0 chicken sweet no 
1  beef hot yes 
2  pork salty no 
3  egg hot yes 
4 chicken sweet no 
5  egg salty yes 
6  beef hot yes 

注:これらの結果は、私の答えが他のものより優れていることを意味しません。

set_valueを使用する:

%timeit recipe.set_value(recipe[recipe.A.isin(like.A) & recipe.B.isin(like.B)].index,'C','yes'); recipe.fillna('no') 
100 loops, best of 3: 2.69 ms per loop 

mergeを使用して、新しいdfを作成:

%timeit df = pd.merge(recipe, like, on=['A','B'], indicator=True, how='left'); df['C'] = np.where(df['_merge'] == 'both', 'yes', 'no') 
100 loops, best of 3: 8.42 ms per loop 

のみmergeを使用する:

%timeit df['C'] = np.where(df['_merge'] == 'both', 'yes', 'no') 
1000 loops, best of 3: 187 µs per loop 

繰り返しますが、それは本当にあなたがタイミングしているかに依存。データの複製には慎重を期してください。

+2

set_valueは実際のイディオムではありません。割り当てを使うだけです。レシピ['C'] = ... – Jeff

+0

私は、このコードもとても賢いと思います。しかし、「合併」に比べてスピードについてどう思いますか? – xirururu

+0

@xirururu私の編集を読む、それはすべてあなたが繰り返しているかもしれない部分に依存する。 – Leb