2017-04-17 4 views
1

この質問は、私が投稿した別の質問に関連しています。 Pandas - check if a string column in one dataframe contains a pair of strings from another dataframeパンダ - データフレーム列にキー:値のペアが含まれているかどうかを確認する

私の目標は、データフレームの2つの異なる列に文字列値のペアが含まれているかどうかをチェックし、条件が満たされている場合は値の1つを抽出します。

私はこのような2つのデータフレーム持っている:「りんご」はdf1['name']で発生し、「リス」はdf1['consumption']に発生し、両方の条件が満たされたならば、「リス」を抽出する場合、私は何をしたいのか

df1 = pd.DataFrame({'consumption':['squirrelate apple', 'monkey likesapple', 
            'monkey banana gets', 'badger/getsbanana', 'giraffe eats grass', 'badger apple.loves', 'elephant is huge', 'elephant/eats/', 'squirrel.digsingrass'], 
        'name': ['apple', 'appleisred', 'banana is tropical', 'banana is soft', 'lemon is sour', 'washington apples', 'kiwi', 'bananas', 'apples']}) 

df2 = pd.DataFrame({'food':['apple', 'apple', 'banana', 'banana'], 'creature':['squirrel', 'badger', 'monkey', 'elephant']}) 

In [187]:df1 
Out[187]: 
      consumption    name 
0  squirrelate apple    apple 
1  monkey likesapple   appleisred 
2 monkey banana gets banana is tropical 
3  badger/getsbanana  banana is soft 
4 giraffe eats grass  lemon is sour 
5 badger apple.loves washington apples 
6  elephant is huge    kiwi 
7  elephant/eats/    bananas 
8 squirrel.digsingrass    apples 

In[188]: df2 
Out[188]: 
    creature food 
0 squirrel apple 
1 badger apple 
2 monkey banana 
3 elephant banana 

はテストですdf1['consumption']から新しい列df['creature']に変更します。何のペア値制約がなかった場合、私は単純なもののように行っている可能性

Out[189]: 
      consumption creature    name 
0  squirrelate apple squirrel    apple 
1  monkey likesapple  NaN   appleisred 
2 monkey banana gets monkey banana is tropical 
3  badger/getsbanana  NaN  banana is soft 
4 giraffe eats grass  NaN  lemon is sour 
5 badger apple.loves badger washington apples 
6  elephant is huge  NaN    kiwi 
7  elephant/eats/ elephant    bananas 
8 squirrel.digsingrass  NaN    apples 

np.where((df1['consumption'].str.contains(<creature_string>, case = False)) & (df1['name'].str.contains(<food_string>, case = False)), df['consumption'].str.extract(<creature_string>), np.nan) 

を私は辞書を作ってみましたので、私はペアを確認する必要があり、結果は次のようになります。値とキーと生き物のような食品は、特定の食品キーのすべての生き物の文字列VARを作り、str.containsを使用して、それらを探して:

unique_food = df2.food.unique() 
food_dict = {elem : pd.DataFrame for elem in unique_food} 
for key in food_dict.keys(): 
    food_dict[key] = df2[:][df2.food == key] 

# create key:value pairs of food key and creature strings 
food_strings = {} 
for key, values in food_dict.items(): 
    food_strings.update({key: '|'.join(map(str, list(food_dict[key]['creature'].unique())))}) 

In[199]: food_strings 
Out[199]: {'apple': 'squirrel|badger', 'banana': 'monkey|elephant'} 

私が今しようとすると問題がありますpply str.contains:

for key, value in food_strings.items(): 
    np.where((df1['name'].str.contains('('+food_strings[key]+')', case = False)) & 
      (df1['consumption'].str.contains('('+food_strings[value]+')', case = False)), df1['consumptions'].str.extract('('+food_strings[value]+')'), np.nan) 

私はKeyError:を取得します。

--------------------------------------------------------------------------- 
KeyError         Traceback (most recent call last) 
<ipython-input-62-7ab718066040> in <module>() 
     1 for key, value in food_strings.items(): 
     2  np.where((df1['name'].str.contains('('+food_strings[key]+')', case = False)) & 
----> 3    (df1['consumption'].str.contains('('+food_strings[value]+')', case = False)), df1['consumption'].str.extract('('+food_strings[value]+')'), np.nan) 

KeyError: 'squirrel|badger' 

私は唯一の値ではなく、キーのためにしようとすると、それは最初のキーのために動作します:値のペアが、2番目ではない:私はリンゴやリスに一致するものを持って

for key in food_strings.keys(): 
    df1['test'] = np.where(df1['consumption'].str.contains('('+food_strings[key]+')', case =False), 
           df1['consumption'].str.extract('('+food_strings[key]+')', expand=False), 
           np.nan) 

df1 
Out[196]: 
      consumption    name  test 
0  squirrelate apple    apple squirrel 
1  monkey likesapple   appleisred  NaN 
2 monkey banana gets banana is tropical  NaN 
3  badger/getsbanana  banana is soft badger 
4 giraffe eats grass  lemon is sour  NaN 
5 badger apple.loves washington apples badger 
6  elephant is huge    kiwi  NaN 
7  elephant/eats/    bananas  NaN 
8 squirrel.digsingrass    apples squirrel 

|バジャー、バナナが恋しい:猿|象。

誰かが助けてくれますか?

+0

「food_dict」の各値には、文字列ではなくデータフレームが含まれていると思います。このエラーは 'for key、food_dict.items():'の値をループするときに発生します。あなたは 'value'を' food_strings [value] 'にデータフレームとして与えます。 – titipata

+1

@titipatそれは残念ですが、良いキャッチです。私は質問を編集し、私が得る正確なエラーを貼り付けた。 – vagabond

答えて

2
d1 = df1.dropna() 
d2 = df2.dropna() 

sump = d1.consumption.values.tolist() 
name = d1.name.values.tolist() 
cret = d2.creature.values.tolist() 
food = d2.food.values.tolist() 

check = np.array(
    [ 
     [c in s and f in n for c, f in zip(cret, food)] 
     for s, n in zip(sump, name) 
    ] 
) 

# create a new series with the index of `d1` where we dropped na 
# then reindex with `df1.index` prior to `assign` 
test = pd.Series(check.dot(d2[['creature']].values).ravel(), d1.index) 
test = test.reindex(df1.index, fill_value='') 
df1.assign(test=test) 

      consumption    name  test 
0  squirrelate apple    apple squirrel 
1  monkey likesapple   appleisred   
2 monkey banana gets banana is tropical monkey 
3  badger/getsbanana  banana is soft   
4 giraffe eats grass  lemon is sour   
5 badger apple.loves washington apples badger 
6  elephant is huge    kiwi   
7  elephant/eats/    bananas elephant 
8 squirrel.digsingrass    apples squirrel 
+0

こんにちは!ありがとう - 素晴らしいソリューション。 1つの問題 - リストにNone値が含まれている場合、それは壊れます。 'TypeError:型 'NoneType'の引数がiterableではありません。 sump、name、cret、foodのために、Nonetypesを持たないリストを作成しました。 'sump = df1 [df1.consumption.notnull()] [' consumption '] values.tolist() ' 'valueError:値の長さがインデックスの長さと一致しません ' – vagabond

+0

zip(sump、name)を反復するときに何とかNaN/None値を取得する必要がありますc-sのいずれかが非タイプであるかf-nが非タイプである場合。 – vagabond

+0

dropnaは動作しません。 。 。私はその後、データフレームを変更するだろう! – vagabond

関連する問題