查找Pandas Dataframe&中的多个字典键。为匹配返回多个值

时间:2018-03-06 00:17:46

标签: python python-3.x pandas dictionary string-matching

如果我的格式化已关闭,第一次发布如此道歉。

这是我的问题:

我创建了一个包含多行文本的Pandas数据框:

<div id='show'></div>
<script type="text/javascript">
    $.ajax({
    url: "/feeds/posts/default?alt=json-in-script",
    type: "get",
    dataType: "jsonp",
    success: function (data) {
        var totalposts = data.feed.openSearch$totalResults.$t;
        document.getElementById('show').innerHTML = "<div class='totalposts'>" + totalposts + "</div>";
        }
    });
</script>

现在我有一个包含以下键/值的字典:

d = {'keywords' :['cheap shoes', 'luxury shoes', 'cheap hiking shoes']}
keywords = pd.DataFrame(d,columns=['keywords'])
In [7]: keywords
Out[7]:
        keywords
0  cheap shoes
1  luxury shoes
2  cheap hiking shoes

我想要做的是找出数据框中是否存在字典中的密钥,如果存在,则返回适当的值

我能够使用以下内容实现这一目标:

labels = {'cheap' : 'budget', 'luxury' : 'expensive', 'hiking' : 'sport'}

但是,输出缺少前两个键,只捕获最后一个“远足”键

for k,v in labels.items():
   keywords['Labels'] = np.where(keywords['keywords'].str.contains(k),v,'No Match')

此外,我还想知道是否有一种方法可以捕获由|分隔的字典中的多个值,所以理想的输出看起来像这样

    keywords            Labels
0   cheap shoes         No Match
1   luxury shoes        No Match
2   cheap hiking shoes  sport

非常感谢任何帮助或指导。

干杯

5 个答案:

答案 0 :(得分:3)

这当然是可能的。这是一种方式。

d = {'keywords': ['cheap shoes', 'luxury shoes', 'cheap hiking shoes', 'nothing']}

keywords = pd.DataFrame(d,columns=['keywords'])

labels = {'cheap': 'budget', 'luxury': 'expensive', 'hiking': 'sport'}

df = pd.DataFrame(d)

def matcher(k):
    x = (i for i in labels if i in k)
    return ' | '.join(map(labels.get, x))

df['values'] = df['keywords'].map(matcher)

#              keywords          values
# 0         cheap shoes          budget
# 1        luxury shoes       expensive
# 2  cheap hiking shoes  budget | sport
# 3             nothing                

答案 1 :(得分:3)

您可以使用"|".join(labels.keys())来获取re.findall()使用的模式。

import pandas as pd
import re

d = {'keywords' :['cheap shoes', 'luxury shoes', 'cheap hiking shoes']}
keywords = pd.DataFrame(d,columns=['keywords'])
labels = {'cheap' : 'budget', 'luxury' : 'expensive', 'hiking' : 'sport'}
pattern = "|".join(labels.keys())

def f(s):
    return "|".join(labels[word] for word in re.findall(pattern, s))

keywords.keywords.map(f)

答案 2 :(得分:1)

坚持你的方法,你可以做到。

arr = np.array([np.where(keywords['keywords'].str.contains(k), v, 'No Match') for k, v in labels.items()]).T
keywords["Labels"] = ["|".join(set(item[ind if ind.sum() == ind.shape[0] else ~ind])) for item, ind in zip(arr, (arr == "No Match"))]

Out[97]: 
             keywords        Labels
0         cheap shoes        budget
1        luxury shoes     expensive
2  cheap hiking shoes  sport|budget

答案 3 :(得分:1)

我喜欢首先使用replace然后找到值的想法。

keywords.assign(
    values=
    keywords.keywords.replace(labels, regex=True)
            .str.findall(f'({"|".join(labels.values())})')
            .str.join(' | ')
)

             keywords          values
0         cheap shoes          budget
1        luxury shoes       expensive
2  cheap hiking shoes  budget | sport

答案 4 :(得分:0)

您可以将split字符串分成不同的列,然后将stack分成多个索引,这样就可以map,将值标签字典添加到值。然后groupby初始索引,concatenate属于每个索引的字符串

keywords['Labels'] = keywords.keywords.str.split(expand=True).stack()\
                     .map(labels).groupby(level=0)\
                     .apply(lambda x: x.str.cat(sep=' | '))



            keywords          Labels
0         cheap shoes          budget
1        luxury shoes       expensive
2  cheap hiking shoes  budget | sport