在 Pandas Dataframe 中查找多个字典键并返回多个匹配值
Posted
技术标签:
【中文标题】在 Pandas Dataframe 中查找多个字典键并返回多个匹配值【英文标题】:Looking up multiple dictionary keys in a Pandas Dataframe & return multiple values for matches 【发布时间】:2018-08-13 18:16:30 【问题描述】:第一次发帖,如果我的格式关闭,请提前道歉。
这是我的问题:
我创建了一个包含多行文本的 Pandas 数据框:
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
此外,我还想知道是否有办法在字典中捕获多个值,用 | 分隔,所以理想的输出应该是这样的
keywords Labels
0 cheap shoes budget
1 luxury shoes expensive
2 cheap hiking shoes budget | sport
非常感谢任何帮助或指导。
干杯
【问题讨论】:
【参考方案1】:这当然是可能的。这是一种方法。
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
【讨论】:
上述效果很好,但有一个跟进。您将如何编辑以上内容以仅捕获完全匹配?例如,如果标签更新为包含“便宜”:“预算”,并且第一个关键字更新为“最便宜的廉价鞋”。运行上述脚本会产生预算 |预算作为“最便宜的廉价鞋”的值 字典可能会增长到容纳更多与单个值相关的单词变体。 你应该使用集合来代替,例如return labels[i] for i in labels if i in k
上述方法可以很好地从最终结果中删除重复值。不过,我仍然遇到部分匹配的奇怪错误。假设我将利物浦添加到关键字d = 'keywords': ['cheapest cheap shoes', 'luxury shoes', 'cheap hiking shoes', 'liverpool']
和“池”到标签labels = 'cheape': 'budget','cheap': 'budget', 'luxury': 'expensive', 'hiking': 'sport', 'pool':'swimming'
会的。谢谢你的帮助,你肯定让我走得更远。非常感谢。【参考方案2】:
您可以使用"|".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)
【讨论】:
【参考方案3】:坚持你的方法,你可以做例如
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
【讨论】:
【参考方案4】:我喜欢先使用 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
【讨论】:
【参考方案5】:您可以将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
【讨论】:
以上是关于在 Pandas Dataframe 中查找多个字典键并返回多个匹配值的主要内容,如果未能解决你的问题,请参考以下文章
python 在Pandas DataFrame中查找连续日期组
Pandas - 在 DataFrame 中的任何位置查找值索引
《Pandas CookBook》---- DataFrame基础操作
Pandas:如何在第二个 DataFrame 的另一列中查找子字符串位置