Как получить список всех повторяющихся элементов с помощью панд в Python?

129

У меня есть список товаров, у которых, вероятно, есть проблемы с экспортом. Я хотел бы получить список повторяющихся элементов, чтобы я мог их вручную сравнить. Когда я пытаюсь использовать дублированный метод pandas , он возвращает только первый дубликат. Есть ли способ получить все дубликаты, а не только первый?

Небольшая часть моего набора данных выглядит так:

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, а также любые другие повторяющиеся записи, а не только первую. Любая помощь приветствуется.

BigHandsome
источник
1
«Дубликаты» могут означать разные вещи «В вашем случае вы хотите рассматривать дубликаты только в одном столбцеID , а не« строки, идентичные в нескольких или во всех столбцах ».
smci

Ответы:

170

Метод №1: распечатать все строки, в которых 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: groupbyпо ID.

>>> 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
DSM
источник
11
Метод №2 просто идеален! Огромное спасибо.
BigHandsome 02
4
Способ № 2 выходит из строя ( «Нет объектов для конкатенации») , если нет Dups
CPBL
4
что g for _ делать?
user77005 05
5
@ user77005 вы , возможно , уже выяснили уже, но на благо каждого, это звучит так: g for (placeholder, g) in df.groupby('bla') if 'bla'; подчеркивание - типичный символ для обозначения неизбежного аргумента, когда мы не хотим использовать его для чего-либо в лямбда-подобном выражении.
stucash 01
7
Метод №1 требует обновления: sortбыл объявлен устаревшим для DataFrames в пользу любого sort_valuesили sort_index связанных SO Q&A
tatlar
138

В Pandas версии 0.17 вы можете установить 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
user666
источник
3
Бинго, вот ответ. Итак: str или str или логическое ... странный выбор API. 'all'было бы более логичным и интуитивно понятным ИМО.
Джарад
93
df[df.duplicated(['ID'], keep=False)]

он вернет вам все повторяющиеся строки.

Согласно документации :

keep: {'first', 'last', False}, по умолчанию 'first'

  • first: пометить дубликаты как True, кроме первого вхождения.
  • last: помечать дубликаты как True, за исключением последнего вхождения.
  • Ложь: пометить все дубликаты как Истинные.
Келли ЧоуЧоу
источник
@dreme это синтаксически неверно и не работает. Несоответствие "]", и он также не возвращает то, что им нужно. Короче, но неверно.
FinancialRadDeveloper
К сожалению, вы правы, @FinancialRadDeveloper, по обоим пунктам. Я удалю свой комментарий. Спасибо, что подняли ошибку.
dreme
4
df [df ['ID']. duplicated () == True] Это вернет все дубликаты
Харипрасад
12

Поскольку я не могу комментировать, поэтому публикую как отдельный ответ

Чтобы найти дубликаты на основе более чем одного столбца, укажите имя каждого столбца, как показано ниже, и он вернет вам весь набор повторяющихся строк:

df[df[['product_uid', 'product_title', 'user']].duplicated() == True]
Дипак
источник
10
df[df['ID'].duplicated() == True]

Это сработало для меня

Харипрасад
источник
2
Фактически добавлять не надо == True, .duplicated()массив уже возвращает bool.
Якуб Вагнер,
3

Используя поэлементную логику или и установив для аргумента take_last дублированного метода pandas значение True и False, вы можете получить набор из вашего фрейма данных, который включает все дубликаты.

df_bigdata_duplicates = 
    df_bigdata[df_bigdata.duplicated(cols='ID', take_last=False) |
               df_bigdata.duplicated(cols='ID', take_last=True)
              ]
Oshbocker
источник
2

Это может быть не решением вопроса, а лишь иллюстрацией примеров:

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
yoonghm
источник
2

sort("ID")похоже, сейчас не работает, кажется устаревшим в соответствии с документом сортировки , поэтому используйте sort_values("ID")вместо этого для сортировки после повторяющегося фильтра, как показано ниже:

df[df.ID.duplicated(keep=False)].sort_values("ID")
Нафиз Кураиши
источник
2

Для моей базы данных дублирование (keep = False) не работало, пока столбец не был отсортирован.

data.sort_values(by=['Order ID'], inplace=True)
df = data[data['Order ID'].duplicated(keep=False)]
LetzerWille
источник
1

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

ПРЕМ ДЖИЛЛА
источник
4
Не могли бы вы дополнить свой ответ более подробными пояснениями? Это будет очень полезно для понимания. Спасибо!
vezunchik
Добро пожаловать в Stack Overflow и спасибо за ваш вклад! Было бы хорошо, если бы вы могли расширить свой ответ объяснением. Здесь вы найдете руководство Как дать хороший ответ . Спасибо!
Дэвид