如何在 python 中使用 pandas 获取所有重复项的列表?

Posted

技术标签:

【中文标题】如何在 python 中使用 pandas 获取所有重复项的列表?【英文标题】:How do I get a list of all the duplicate items using pandas in python? 【发布时间】:2013-01-17 09:52:17 【问题描述】:

我有一份可能存在出口问题的物品清单。我想获取重复项目的列表,以便手动比较它们。当我尝试使用 pandas duplicated method 时,它只返回第一个副本。有没有办法获取所有重复项,而不仅仅是第一个?

我的数据集的一小部分如下所示:

ID,ENROLLMENT_DATE,TRAINER_MANAGING,TRAINER_OPERATOR,FIRST_VISIT_DATE
1536D,12-Feb-12,"06DA1B3-Lebanon NH",,15-Feb-12
F15D,18-May-12,"06405B2-Lebanon NH",,25-Jul-12
8096,8-Aug-12,"0643D38-Hanover NH","0643D38-Hanover NH",25-Jun-12
A036,1-Apr-12,"06CB8CF-Hanover NH","06CB8CF-Hanover NH",9-Aug-12
8944,19-Feb-12,"06D26AD-Hanover NH",,4-Feb-12
1004E,8-Jun-12,"06388B2-Lebanon NH",,24-Dec-11
11795,3-Jul-12,"0649597-White River VT","0649597-White River VT",30-Mar-12
30D7,11-Nov-12,"06D95A3-Hanover NH","06D95A3-Hanover NH",30-Nov-11
3AE2,21-Feb-12,"06405B2-Lebanon NH",,26-Oct-12
B0FE,17-Feb-12,"06D1B9D-Hartland VT",,16-Feb-12
127A1,11-Dec-11,"064456E-Hanover NH","064456E-Hanover NH",11-Nov-12
161FF,20-Feb-12,"0643D38-Hanover NH","0643D38-Hanover NH",3-Jul-12
A036,30-Nov-11,"063B208-Randolph VT","063B208-Randolph VT",
475B,25-Sep-12,"06D26AD-Hanover NH",,5-Nov-12
151A3,7-Mar-12,"06388B2-Lebanon NH",,16-Nov-12
CA62,3-Jan-12,,,
D31B,18-Dec-11,"06405B2-Lebanon NH",,9-Jan-12
20F5,8-Jul-12,"0669C50-Randolph VT",,3-Feb-12
8096,19-Dec-11,"0649597-White River VT","0649597-White River VT",9-Apr-12
14E48,1-Aug-12,"06D3206-Hanover NH",,
177F8,20-Aug-12,"063B208-Randolph VT","063B208-Randolph VT",5-May-12
553E,11-Oct-12,"06D95A3-Hanover NH","06D95A3-Hanover NH",8-Mar-12
12D5F,18-Jul-12,"0649597-White River VT","0649597-White River VT",2-Nov-12
C6DC,13-Apr-12,"06388B2-Lebanon NH",,
11795,27-Feb-12,"0643D38-Hanover NH","0643D38-Hanover NH",19-Jun-12
17B43,11-Aug-12,,,22-Oct-12
A036,11-Aug-12,"06D3206-Hanover NH",,19-Jun-12

我的代码目前看起来像这样:

df_bigdata_duplicates = df_bigdata[df_bigdata.duplicated(cols='ID')]

有几个重复的项目。但是,当我使用上面的代码时,我只得到第一项。在 API 参考中,我看到了如何获得最后一项,但我想拥有所有这些,这样我就可以直观地检查它们以了解为什么会出现差异。因此,在此示例中,我想获取所有三个 A036 条目以及 11795 条目和任何其他重复的条目,而不是仅获取第一个条目。非常感谢任何帮助。

【问题讨论】:

“重复”可能意味着不同的事情”在您的情况下,您只想考虑 单列中的重复ID,而不是“多列或所有列中相同的行"。 【参考方案1】:

方法 #1:打印 ID 为重复 ID 之一的所有行:

>>> import pandas as pd
>>> df = pd.read_csv("dup.csv")
>>> ids = df["ID"]
>>> df[ids.isin(ids[ids.duplicated()])].sort("ID")
       ID ENROLLMENT_DATE        TRAINER_MANAGING        TRAINER_OPERATOR FIRST_VISIT_DATE
24  11795       27-Feb-12      0643D38-Hanover NH      0643D38-Hanover NH        19-Jun-12
6   11795        3-Jul-12  0649597-White River VT  0649597-White River VT        30-Mar-12
18   8096       19-Dec-11  0649597-White River VT  0649597-White River VT         9-Apr-12
2    8096        8-Aug-12      0643D38-Hanover NH      0643D38-Hanover NH        25-Jun-12
12   A036       30-Nov-11     063B208-Randolph VT     063B208-Randolph VT              NaN
3    A036        1-Apr-12      06CB8CF-Hanover NH      06CB8CF-Hanover NH         9-Aug-12
26   A036       11-Aug-12      06D3206-Hanover NH                     NaN        19-Jun-12

但我想不出一个很好的方法来防止重复ids 这么多次。我更喜欢方法#2:ID 上的groupby

>>> pd.concat(g for _, g in df.groupby("ID") if len(g) > 1)
       ID ENROLLMENT_DATE        TRAINER_MANAGING        TRAINER_OPERATOR FIRST_VISIT_DATE
6   11795        3-Jul-12  0649597-White River VT  0649597-White River VT        30-Mar-12
24  11795       27-Feb-12      0643D38-Hanover NH      0643D38-Hanover NH        19-Jun-12
2    8096        8-Aug-12      0643D38-Hanover NH      0643D38-Hanover NH        25-Jun-12
18   8096       19-Dec-11  0649597-White River VT  0649597-White River VT         9-Apr-12
3    A036        1-Apr-12      06CB8CF-Hanover NH      06CB8CF-Hanover NH         9-Aug-12
12   A036       30-Nov-11     063B208-Randolph VT     063B208-Randolph VT              NaN
26   A036       11-Aug-12      06D3206-Hanover NH                     NaN        19-Jun-12

【讨论】:

方法 #2 非常完美!非常感谢。 方法#2失败(“没有要连接的对象”)如果没有重复 g for _ 是做什么的? @user77005 你可能已经想通了,但是为了大家的利益,它是这样写的:g for (placeholder, g) in df.groupby('bla') if 'bla';下划线是不可避免的参数占位符的典型符号,我们不想在类似 lambda 的表达式中使用它。 方法 #1 需要更新:sort 已弃用 DataFrames,取而代之的是 sort_valuessort_index Related SO Q&A【参考方案2】:

使用 Pandas 0.17 版,您可以在 duplicated 函数中设置 'keep = False' 以获取所有重复项。

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(['a','b','c','d','a','b'])

In [3]: df
Out[3]: 
       0
    0  a
    1  b
    2  c
    3  d
    4  a
    5  b

In [4]: df[df.duplicated(keep=False)]
Out[4]: 
       0
    0  a
    1  b
    4  a
    5  b

【讨论】:

宾果游戏,答案就在这里。所以:str 或 str 或 boolean...奇怪的 API 选择。 'all' 会更符合逻辑和直观的 IMO。 @Jarad 你不觉得keep=False 的意思是“是的,保留所有东西”很直观吗?奇怪的。 /s【参考方案3】:
df[df.duplicated(['ID'], keep=False)]

它会将所有重复的行返回给您。

根据documentation:

keep : ‘first’, ‘last’, False, 默认‘first’

first :将重复项标记为 True,但第一次出现除外。 last :将重复项标记为 True,但最后一次出现除外。 False : 将所有重复项标记为 True。

【讨论】:

对我来说似乎是最好的解决方案【参考方案4】:

由于我无法发表评论,因此作为单独的答案发布

要根据多个列查找重复项,请提及每个列名 如下,它将返回所有重复的行集:

df[df[['product_uid', 'product_title', 'user']].duplicated() == True]

或者,

df[df[['product_uid', 'product_title', 'user']].duplicated()]

【讨论】:

【参考方案5】:
df[df['ID'].duplicated() == True]

这对我有用

【讨论】:

其实不用加== True.duplicated()已经返回bool数组了。【参考方案6】:

使用逐元素逻辑或并将 pandas 重复方法的 take_last 参数设置为 True 和 False,您可以从包含所有重复项的数据帧中获取一个集合。

df_bigdata_duplicates = 
    df_bigdata[df_bigdata.duplicated(cols='ID', take_last=False) |
               df_bigdata.duplicated(cols='ID', take_last=True)
              ]

【讨论】:

【参考方案7】:

sort("ID") 现在似乎不起作用,似乎已根据sort doc 弃用,因此请使用sort_values("ID") 在重复过滤器之后进行排序,如下所示:

df[df.ID.duplicated(keep=False)].sort_values("ID")

【讨论】:

【参考方案8】:

这可能不是问题的解决方案,而是举例说明:

import pandas as pd

df = pd.DataFrame(
    'A': [1,1,3,4],
    'B': [2,2,5,6],
    'C': [3,4,7,6],
)

print(df)
df.duplicated(keep=False)
df.duplicated(['A','B'], keep=False)

输出:

   A  B  C
0  1  2  3
1  1  2  4
2  3  5  7
3  4  6  6

0    False
1    False
2    False
3    False
dtype: bool

0     True
1     True
2    False
3    False
dtype: bool

【讨论】:

【参考方案9】:

对于我的数据库,重复(keep=False)直到列被排序后才起作用。

data.sort_values(by=['Order ID'], inplace=True)
df = data[data['Order ID'].duplicated(keep=False)]

【讨论】:

【参考方案10】:

df[df.duplicated(['ID'])==True].sort_values('ID')

所有列值的重复行及其索引位置

def dup_rows_index(df):
  dup = df[df.duplicated()]
  print('Duplicated index loc:',dup[dup == True ].index.tolist())
  return dup

【讨论】:

拜托,你能用更详细的解释来扩展你的答案吗?这对理解非常有用。谢谢! 欢迎来到 Stack Overflow 并感谢您的贡献!如果您可以通过解释来扩展您的答案,那就太好了。在这里您可以找到指南How to give a good answer。谢谢!

以上是关于如何在 python 中使用 pandas 获取所有重复项的列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中使用 Pandas 按列分组

如何使用 Python 的 ID 获取 Google Drive 上文件的 url

如何:Python Pandas 获取当前股票数据

如何从 print() 编写的字符串中获取 Python pandas DataFrame?

如何在没有标头信息的 Python 2.7-Pandas 中读取数据

如何使用 python 和 pandas 将 Csv 文件转换为 libsvm?