Pandas - 检查数据帧列是否包含字典中的键:值对

时间:2017-04-17 04:24:58

标签: python string pandas dictionary string-matching

这个问题与我发布的另一个问题有关。 Pandas - check if a string column in one dataframe contains a pair of strings from another dataframe

我的目标是检查数据框的两个不同列是否包含一对字符串值,如果满足条件,则提取其中一个值。

我有两个这样的数据框:

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['name']和' squirrel'发生在df1['consumption'],如果两个条件都满足,则提取“松鼠”。从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'}

问题是我现在尝试应用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'

当我只尝试值而不是键时,它适用于第一个键:值对但不适用于第二个键:

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

我找到了与苹果和松鼠相匹配的獾但是错过了香蕉:猴子|大象。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分: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
相关问题