我看到很多类似的问题,但不完全是我的情况。
我有 2 个数据框,每个数据框都有很多列。一个非常简化的再现是:
df1:
serial_num name
0 39jr93j Phyl
1 <NA> Gil
2 21pr12n Ann
df2:
serial_num name alternate_nombre different_name nm_alternate
0 5c2v40l Jill Jyl. Jill Smith. Gil Smyth
1 21pr12n Karen Caren. Karen Ann. Caryn Anne
2 39jr93j Phyllis Fillus Phil Phyllus
想要的结果:
serial_num name
0 39jr93j Phyl
1 5c2v40l Gil
2 21pr12n Ann
DF1 缺少一些序列号,但
df1
中唯一的名称列可能与 df2
中使用的拼写不同。我想查找 df1['serial_num']
中缺少 df2
的所有行来填充它。但是在 df2
中,存在大量备用名称列,因此无法逐项列出要查找的列df1
中的名称可能是df2
中的名称/备用名称的子字符串。所以我想看看整个 df2
就好像 df1['name']
是一个子串一样。
然后我想用
df1['serial_num']
来填写相应的df2['serial_num']
。
如果不迭代行,我无法理解如何做到这一点。
我使用以下内容创建了缺少的行子集
df['serial_num']
:
missing_serials = df1[df1['serial_num'].isnull()]
我看到一些在整个数据帧中搜索子字符串的解决方案,如下所示:
df2[df2.apply(lambda r: r.str.contains('specific static substring', case=False).any(), axis=1)]
但我似乎无法弄清楚如何在不迭代行的情况下用我的
'specific static substring'
替换 missing_serials['name']
,或者当我无法预测哪一列将匹配时如何组合我的 missing_serials
和 df2
。我开始怀疑使用 missing_serials
子数据框是否是正确的方法,因为我不知道如何将值返回到 df1
中。也许有某种更好的 df1['serial_num'].fillna
方法?
就个人而言,我使用 df1.apply看到此选项。
然后我们将创建一个临时 DataFrame,其中包含 df2 中可能包含匹配项的所有可能列的行和值的唯一组合。接下来,我们将使用 str.contains 搜索所有列并与 df1 合并。
df2_long = pd.concat([df2[['serial_num']], df2.drop(columns=['serial_num']).stack().reset_index(drop=True, level=1)], axis=1)
df2_long.columns = ['serial_num', 'name_variant']
用于查找匹配项并替换serial_num的函数:
def find_serial_num(row, df2_long):
if pd.isnull(row['serial_num']):
match = df2_long[df2_long['name_variant'].str.contains(row['name'], case=False, na=False)]
if not match.empty:
return match.iloc[0]['serial_num']
return row['serial_num']
最后,我们将函数应用到 df1:
df1['serial_num'] = df1.apply(find_serial_num, df2_long=df2_long, axis=1)