使用 str.contains(),我可以回溯哪些比较器导致"错误"结果吗?



我有一个Pandas数据帧df1,它包含一列名称和相关的数据列。我有另一个df2,它有一列来自不同来源的名称。两者在格式上存在差异。在这个例子中,df2去掉后缀,使用昵称而不是正式名称(但我不知道数据集中可能存在其他格式差异(:

df1 = pd.DataFrame([('Jordan Smith Jr.', 25, 180),
('Andrew Johnson', 34, 200),
('Anthony Tipton III', 42, 175),
('Chris Black', 24, 160)],
columns=('name', 'age', 'weight'))
df2 = pd.DataFrame([('Jordan Smith'),
('Drew Johnson'),
('Anthony Tipton')],
columns=('name'))

我想过滤并返回df1中存在于df2中的人员的行。df1包含df2,因此唯一的布尔比较失败将是由于格式差异。我想收集df2中比较不好的一组名称,这样我就可以检查它们并进行相应的处理。我可以这样过滤df1:

df1 = df1[df1['name'].str.contains('|'.join(df2['name'])]

这处理了后缀差异,并以我感到满意的方式减少了比较失败的次数,但有没有一种简单的方法可以收集df2中比较不好的成员?我可以用循环迭代,但我觉得可能有一种更优雅的方法

---------------编辑------------------

上面的代码返回了我想要的一半,我不寻求帮助(除非有更好的、完全不同的方法(:

>>>df1
[('Jordan Smith Jr.', 25, 180),
('Anthony Tipton III', 42, 175)]

我正在寻找一种方法来撤销df2中的名称,这些名称在评估此检查时没有被解析为df1中任何"名称"的"True":

df1['name'].str.contains('|'.join(df2['name'])

我可以用类似的东西来实现这一点:

for name in df2:
temp = df1['name'].str.contains(name)
if temp.any():
*append name to collection list/dataframe/etc.*

但我觉得还有更好的办法。

IIUC,您想在df2中识别在df1中从未匹配的名称吗?

您可以在extractall:上使用设置操作

set(df2['name']).difference(df1['name'].str.extractall(f"({'|'.join(df2['name'])})")[0])

输出:{'Drew Johnson'}

中级,所有匹配的术语:

df1['name'].str.extractall(f"({'|'.join(df2['name'])})")[0]
match
0  0          Jordan Smith
2  0        Anthony Tipton
Name: 0, dtype: object

由于两个数据帧中没有一个名称完全匹配,我将添加一个来说明:

In[1]: df1 = pd.DataFrame([('Jordan Smith Jr.', 25, 180),
('Andrew Johnson', 34, 200),
('Anthony Tipton III', 42, 175),
('Chris Black', 24, 160)],
columns=('name', 'age', 'weight'))
In[2]: df2 = pd.DataFrame([('Jordan Smith'),
('Drew Johnson'),
('Anthony Tipton'),
('Chris Black')],  # <-- added one here
columns=['name'])  # had to put it into square brackets to work

然后,您可以通过在两组名称之间找到.intersection()来找到那些完全相交的名称:

In[1]: name_intersection = list(set(df1['name']).intersection(set(df2['name'])))
In[2]: name_intersection
Out[2]: ['Chris Black']  # shows fully intersecting names only

然后,您可以在条件之前使用~df1中筛选出匹配的名称

In[1]: df_unmatched = df1[~df1.name.isin(name_intersection)]
In[2]: df_unmatched
Out[2]:     name                 age  weight
0   Jordan Smith Jr.     25   180
1   Andrew Johnson       34   200
2   Anthony Tipton III   42   175

如果您的问题是查找不完全相同的名称,这将起作用。你可以进一步使用你的方法来过滤掉名字,但如果没有额外的例子,我无法为你提供一个通用的方法,因此"Andrew"是"Drew",但可能有"Joseph"是"Joe",或者其他模式。

最新更新