如何删除重复项,但在特定的其他列不为null时保留行(Pandas)

2024-09-30 00:42:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有很多重复的记录,其中一些有银行账户。我想用银行账户保存这些记录。在

基本上类似于:

if there are two Tommy Joes:
     keep the one with a bank account

我尝试过用下面的代码进行重复数据消除,但它没有银行帐户来保持重复。在

^{pr2}$

您可以看到索引0和3被保留。这些拥有银行账户的客户版本被删除。我的预期结果是会有相反的结果。删除没有银行帐户的受骗者。在

我曾考虑过先按银行账户进行分类,但我有太多的数据,我不确定如何“感觉检查”它,看看它是否有效。在

感谢任何帮助。在

这里有一些类似的问题,但它们似乎都有可以排序的值,例如年龄等。这些散列的银行账号非常混乱

编辑:

在我的真实数据集上尝试答案的一些结果。在

@Erfan按subset+bank排序值的方法

重复数据消除后剩余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 

在@亚当.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

不知道为什么会有差异,但两者都很相似。在


Tags: 数据lambdadfif排序记录账户银行
3条回答

您应该按bank列对值进行排序,并使用na_position='last'(因此.drop_duplicates(..., keep='first')将保留一个非na的值)。在

试试这个:

import pandas as pd
import numpy as np

df = pd.DataFrame({'firstname': ['foo Bar', 'Bar Bar', 'Foo Bar'],
                   'lastname': ['Foo Bar', 'Bar', 'Foo Bar'],
                   'email': ['Foo bar', 'Bar', 'Foo Bar'],
                   'bank': [np.nan, 'abc', 'xyz']})

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

# save unique records
dfiban_uniq = df.loc[uniq_indx]

print(dfiban_uniq)

输出:

^{pr2}$

(这只是您的原始代码,在uniq_indx = ...的开头加上.sort_values(by="bank", na_position='last')

方法1:下部结构,排序并删除重复项

这也适用于许多列

subset = ['firstname', 'lastname']

df[subset] = df[subset].apply(lambda x: x.str.lower())
df.sort_values(subset + ['bank'], inplace=True)
df.drop_duplicates(subset, inplace=True)
^{pr2}$

方法二:groupby,agg,first

不容易推广到许多列

df.groupby([df['firstname'].str.lower(), df['lastname'].str.lower()], sort=False)\
  .agg({'email':'first','bank':'first'})\
  .reset_index()
  firstname lastname    email bank
0   foo bar  foo bar  Foo bar  xyz
1   bar bar      bar      Bar  abc

您可以按drop_duplicates之前的银行帐户进行排序,将重复项放在NaN最后:

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)
.sort_values(by='bank')  # here we sort values by bank column
.drop_duplicates(subset=['firstname', 'lastname', 'email'], keep='first')).index

相关问题 更多 >

    热门问题