保留第一个重复行,但保存第一个的索引。

20
我正在尝试在pandas数据帧中找到重复行,但要跟踪原始重复的索引。
df=pd.DataFrame(data=[[1,2],[3,4],[1,2],[1,4],[1,2]],columns=['col1','col2'])

df
Out[15]: 
   col1  col2
0     1     2
1     3     4
2     1     2
3     1     4
4     1     2

duplicate_bool = df.duplicated(subset=['col1','col2'], keep='first')
duplicate = df.loc[duplicate_bool == True]

duplicate
Out[16]: 
   col1  col2
2     1     2
4     1     2

有没有一种方法可以添加一个列,该列引用第一个重复项的索引(保留的那个)?

duplicate
Out[16]: 
   col1  col2  index_original
2     1     2               0
4     1     2               0

注意:在我的情况下,df可能非常非常大...

如果有3个重复项怎么办? - cs95
好的,我编辑了这个问题。 - gabboshow
你能否添加输出不止一个重复项的代码? - Bharath M Shetty
如果这个答案有帮助,请投票并接受。谢谢。 - cs95
如果我有90列,我该怎么办? - Fernando.F
3个回答

15

使用 groupby,创建一个新的索引列,然后调用 duplicated

df['index_original'] = df.groupby(['col1', 'col2']).col1.transform('idxmin')    
df[df.duplicated(subset=['col1','col2'], keep='first')]

   col1  col2  index_original
2     1     2               0
4     1     2               0

细节

我首先按前两列进行分组,然后调用transform+idxmin来获取每个组的第一个索引。

df.groupby(['col1', 'col2']).col1.transform('idxmin') 

0    0
1    1
2    0
3    3
4    0
Name: col1, dtype: int64

duplicated 给我一个布尔掩码,用于标记我想要保留的值:

df.duplicated(subset=['col1','col2'], keep='first')

0    False
1    False
2     True
3    False
4     True
dtype: bool

其他部分只是布尔索引


@cᴏʟᴅsᴘᴇᴇᴅ 你好,该解决方案对于示例非常有效,但是当我尝试将其应用于我的实际情况时,它需要很长时间……大小为(11861200,2)。 - gabboshow
1
@gabboshow 有1100万行?那真是吓人啊...你应该尝试使用“dask”并行化你的groupby操作,这样可以处理巨大的数据框。 - cs95
我认为这仍然会很慢...有没有不使用groupby的方法,或者这是最快的解决方案? - gabboshow
1
如果你正在使用pandas,那么最好的方法是使用groupby...你可以尝试在numpy标签中提出类似的问题,看看divakar是否有一个numpy的解决方案...(他可能有)。 - cs95
@cs95 如果我有90个列,我该怎么办? - Fernando.F

11

也许您不再需要这个答案,但是还有另一种方法可以找到重复的行:

df=pd.DataFrame(data=[[1,2],[3,4],[1,2],[1,4],[1,2]],columns=['col1','col2'])

给定上述DataFrame,你可以使用groupby进行操作,但是对于更大的DataFrame,这种方法会变得缓慢,因此你可以使用

DataFrame.duplicated(subset=None, keep='first')

返回表示重复行的布尔序列。

根据文档,它返回一个布尔序列,换句话说,一个布尔掩码,因此你可以使用该掩码来操作DataFrame,或者只是可视化重复的行:

>>> df[df.duplicated()]
   col1  col2
2     1     2
4     1     2

如果您有一个拥有更多列的DataFrame,并且想要按特定列查找重复行,则可以向函数提供要查找的列的列表,例如以下DataFrame:

# List of Tuples
students = [('jack', 34, 'Sydeny'),
            ('Riti', 30, 'Delhi'),
            ('Aadi', 16, 'New York'),
            ('Riti', 30, 'Delhi'),
            ('Riti', 30, 'Delhi'),
            ('Riti', 30, 'Mumbai'),
            ('Aadi', 40, 'London'),
            ('Sachin', 30, 'Delhi')
            ]
# Create a DataFrame object
df = pd.DataFrame(students, columns=['Name', 'Age', 'City'])

如果你想找到所有列中的重复行并进行可视化,只需执行:

>>> df[df.duplicated()]
   Name  Age   City
3  Riti   30  Delhi
4  Riti   30  Delhi

但是如果你只想查找重复的行,只考虑两列,例如“姓名”和“年龄”,只需执行:

>>> df[df.duplicated(['Name', 'Age'])]
   Name  Age    City
3  Riti   30   Delhi
4  Riti   30   Delhi
5  Riti   30  Mumbai

或者只有一个列,例如“名称”:

>>> df[df.duplicated(['Name'])]
   Name  Age    City
3  Riti   30   Delhi
4  Riti   30   Delhi
5  Riti   30  Mumbai
6  Aadi   40  London
以上示例仅返回了重复的行,而没有返回“原始行”,因此如果您查看示例,如果按照给定的标准有三个重复的行,则只会返回两个。

非常棒的努力!对于更大的数据框来说肯定更快。+10 :) - Carmoreno
1
keep="first"让我有些困惑——使用keep=False会返回所有重复行,而不是丢掉第一个。我知道这不是OP的目标,但对于未来的访问者可能会有帮助。 - ggorlen

3
len(df[df.duplicated()])

使用这种方法,您可以计算数据集中重复项的数量。


这并没有回答楼主的问题。 - ggorlen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接