我有许多重复的记录,其中一些有银行账户。 我想保留带有银行账户的记录。
基本上像这样:
if there are two Tommy Joes:
keep the one with a bank account
我已经尝试使用以下代码进行去重,但它仍然保留了没有银行账户的重复项。
df = pd.DataFrame({'firstname':['foo Bar','Bar Bar','Foo Bar','jim','john','mary','jim'],
'lastname':['Foo Bar','Bar','Foo Bar','ryan','con','sullivan','Ryan'],
'email':['Foo bar','Bar','Foo Bar','jim@com','john@com','mary@com','Jim@com'],
'bank':[np.nan,'abc','xyz',np.nan,'tge','vbc','dfg']})
df
firstname lastname email bank
0 foo Bar Foo Bar Foo bar NaN
1 Bar Bar Bar Bar abc
2 Foo Bar Foo Bar Foo Bar xyz
3 jim ryan jim@com NaN
4 john con john@com tge
5 mary sullivan mary@com vbc
6 jim Ryan Jim@com dfg
# get the index of unique values, based on firstname, lastname, email
# convert to lower and remove white space first
uniq_indx = (df.dropna(subset=['firstname', 'lastname', 'email'])
.applymap(lambda s:s.lower() if type(s) == str else s)
.applymap(lambda x: x.replace(" ", "") if type(x)==str else x)
.drop_duplicates(subset=['firstname', 'lastname', 'email'], keep='first')).index
# save unique records
dfiban_uniq = df.loc[uniq_indx]
dfiban_uniq
firstname lastname email bank
0 foo Bar Foo Bar Foo bar NaN # should not be here
1 Bar Bar Bar Bar abc
3 jim ryan jim@com NaN # should not be here
4 john con john@com tge
5 mary sullivan mary@com vbc
# I wanted these duplicates to appear in the result:
firstname lastname email bank
2 Foo Bar Foo Bar Foo Bar xyz
6 jim Ryan Jim@com dfg
你可以看到索引0和3被保留了下来。这些有银行账户的客户的版本被删除了。我的期望结果是相反的,删除那些没有银行账户的重复记录。
我考虑过先按银行账户排序,但是我的数据非常多,我不确定如何“感性检查”它是否有效。
任何帮助都将不胜感激。
这里有一些类似的问题,但所有这些问题似乎都有可以排序的值,例如年龄等。这些哈希银行账户号码非常混乱。
编辑:
尝试在我的真实数据集上使用答案的一些结果。
@Erfan的方法先对子集+银行进行排序
去重后剩下58594条记录:
subset = ['firstname', 'lastname']
df[subset] = df[subset].apply(lambda x: x.str.lower())
df[subset] = df[subset].apply(lambda x: x.replace(" ", ""))
df.sort_values(subset + ['bank'], inplace=True)
df.drop_duplicates(subset, inplace=True)
print(df.shape[0])
58594
@Adam.Er8 根据银行进行排序值的答案。去重后仍剩下59170条记录:
uniq_indx = (df.sort_values(by="bank", na_position='last').dropna(subset=['firstname', 'lastname', 'email'])
.applymap(lambda s: s.lower() if type(s) == str else s)
.applymap(lambda x: x.replace(" ", "") if type(x) == str else x)
.drop_duplicates(subset=['firstname', 'lastname', 'email'], keep='first')).index
df.loc[uniq_indx].shape[0]
59170
不确定为什么会有差异,但两者足够相似。
keep='last'
而不是keep='first'
?last有银行。 - MEdwin