在多个列中查找重复项并删除行 - 熊猫

时间:2016-07-24 19:29:06

标签: python pandas rows

如果名称出现在任何后续行中,我想删除该行。主要是我不知道如何获得找到的重复索引,然后使用该索引号从df中删除它。

import pandas as pd
data = {'interviewer': ['Jason', 'Molly', 'Jermaine', 'Jake', 'Amy'], 
        'candidate': ['Bob', 'Jermaine', 'Ahmed', 'Karl', 'Molly'],
        'year': [2012, 2012, 2013, 2014, 2014], 
        'reports': [4, 24, 31, 2, 3]}

df = pd.DataFrame(data)
#names = pd.unique(df[['interviewer', 'candidate']].values.ravel()).tolist()

mt = []

for i, c in zip(df.interviewer, df.candidate):
    print i, c
    if i not in mt:
        if c not in mt:
            mt.append(df.loc[(df.interviewer == i) & (df.candidate == c)] )
    else:
        continue

我的想法是使用mt作为传递给df.drop的列表并删除带有这些索引的行。我想要的结果是没有看到莫莉或杰梅因再次出现在指数2或4中 - df.drop([2,4], inplace=True)

EDITED

我找到了一种方法来创建我想要传递给它的索引列表:

import pandas as pd
data = {'interviewer': ['Jason', 'Molly', 'Jermaine', 'Jake', 'Amy'], 
        'candidate': ['Bob', 'Jermaine', 'Ahmed', 'Karl', 'Molly'],
        'year': [2012, 2012, 2013, 2014, 2014], 
        'reports': [4, 24, 31, 2, 3]}

df = pd.DataFrame(data)
#print df
counter = -1
bad_rows = []
names = []
for i, c in zip(df.interviewer, df.candidate):
    print i, c

    counter += 1
    print counter
    if i not in names:
        names.append(i)
    else:
        bad_rows.append(counter)
    if c not in names:
        names.append(c)
    else:
        bad_rows.append(counter)

#print df.drop(bad_rows)

然而,必须有一个更聪明的方法来做到这一点,也许是@Ami_Tavory回答itertools的事情?

2 个答案:

答案 0 :(得分:1)

(在写这个答案的时候,口头描述和代码示例之间存在一些差异。)

您可以使用isin检查某个项目是否出现在不同的列中,如下所示:

In [5]: df.candidate.isin(df.interviewer)
Out[5]: 
0    False
1     True
2    False
3    False
4     True
Name: candidate, dtype: bool

因此,您可以执行类似

的操作
df[~df.candidate.isin(df.interviewer)]

请注意,这与原始代码匹配,而不是后续行的规范。如果您只想在后续行中删除,我会选择itertools,例如:

In [18]: bads = [i for ((i, cn), (j, iv)) in itertools.product(enumerate(df.candidate), enumerate(df.interviewer)) if j >=i and cn == iv]

In [19]: df[~df.index.isin(bads)]
Out[19]: 
  candidate interviewer  reports  year
0       Bob       Jason        4  2012
2     Ahmed    Jermaine       31  2013
3      Karl        Jake        2  2014
4     Molly         Amy        3  2014

此外,如果您想删除后续行,只需将内容更改为

即可
In [18]: bads = [j for ((i, cn), (j, iv)) in itertools.product(enumerate(df.candidate), enumerate(df.interviewer)) if j >=i and cn == iv]

答案 1 :(得分:0)

我为我想做的事情做了一个功能。使用df.index可以安全地用于任何数字索引。

def drop_dup_rows(df):
    names = []
    for i, c, ind in zip(df.interviewer, df.candidate, df.index.tolist()):
        if any(x in names for x in [i, c]):
            df.drop(ind, inplace=True)
        else:
            names.extend([i,c])
    return df