Làm cách nào để lấy danh sách tất cả các mục trùng lặp bằng cách sử dụng gấu trúc trong python?


126

Tôi có một danh sách các mặt hàng có thể có một số vấn đề xuất khẩu. Tôi muốn nhận danh sách các mục trùng lặp để tôi có thể so sánh chúng theo cách thủ công. Khi tôi cố gắng sử dụng phương pháp nhân bản gấu trúc , nó chỉ trả về bản sao đầu tiên. Có cách nào để lấy tất cả các bản sao và không chỉ cái đầu tiên không?

Một phần nhỏ trong tập dữ liệu của tôi trông như thế này:

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

Mã của tôi hiện tại trông như thế này:

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

Có một vài mục trùng lặp. Nhưng, khi tôi sử dụng mã trên, tôi chỉ nhận được mục đầu tiên. Trong tài liệu tham khảo API, tôi thấy cách tôi có thể nhận được mục cuối cùng, nhưng tôi muốn có tất cả chúng để tôi có thể kiểm tra trực quan chúng để xem tại sao tôi nhận được sự khác biệt. Vì vậy, trong ví dụ này, tôi muốn lấy tất cả ba mục nhập A036 và cả 11795 mục nhập và bất kỳ mục nhập trùng lặp nào khác, thay vì chỉ một mục đầu tiên. Bất cứ sự giúp đỡ nào đều được đánh giá cao.


1
"Các bản sao" có thể có nghĩa là nhiều thứ khác nhau "Trong trường hợp của bạn, bạn chỉ muốn xem xét các bản sao trong một cột duy nhấtID , không phải" các hàng giống hệt nhau trong nhiều hoặc tất cả các cột ".
smci

Câu trả lời:


169

Phương pháp # 1: in tất cả các hàng có ID là một trong các ID trong bản sao:

>>> 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

nhưng tôi không thể nghĩ ra một cách hay để tránh lặp lại idsnhiều lần như vậy. Tôi thích phương pháp số 2: groupbytrên 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

11
Phương pháp số 2 chỉ là hoàn hảo! Cảm ơn bạn rất nhiều.
BigHandsome

4
Phương pháp # 2 không thành công ("Không có đối tượng nào để nối") nếu không có lỗi
CPBL

4
những gì g for _ làm gì?
user77005

5
@ user77005 bạn có thể đã tìm ra đã có, nhưng vì lợi ích của mọi người, nó đọc như thế này: g for (placeholder, g) in df.groupby('bla') if 'bla'; dấu gạch dưới là một biểu tượng điển hình cho chỗ dành sẵn của một đối số không thể tránh khỏi mà chúng ta không muốn sử dụng nó cho bất kỳ thứ gì trong một biểu thức giống lambda.
stucash

7
Phương pháp # 1 cần phải được cập nhật: sortđã bị phản đối cho DataFrames ủng hộ của một trong hai sort_valueshoặc sort_index liên quan SO Q & A
tatlar

138

Với phiên bản Pandas 0.17, bạn có thể đặt 'keep = False' trong chức năng nhân bản để nhận tất cả các mục trùng lặp.

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

3
Bingo, có câu trả lời. Vì vậy: str hoặc str hoặc boolean ... lựa chọn API kỳ quặc. 'all'IMO sẽ logic và trực quan hơn.
Jarad

92
df[df.duplicated(['ID'], keep=False)]

nó sẽ trả lại tất cả các hàng trùng lặp cho bạn.

Theo tài liệu :

giữ: {'đầu tiên', 'cuối cùng', Sai}, mặc định 'đầu tiên'

  • đầu tiên: Đánh dấu các bản sao là Đúng ngoại trừ lần xuất hiện đầu tiên.
  • cuối cùng: Đánh dấu các bản sao là Đúng ngoại trừ lần xuất hiện cuối cùng.
  • Sai: Đánh dấu tất cả các bản sao là Đúng.

@dreme, điều này không chính xác về mặt cú pháp, cũng như không hoạt động. Không khớp ']' và nó cũng không trả lại những gì họ cần. Nó ngắn hơn, nhưng sai.
FinancialRadDeveloper

Rất tiếc, bạn đúng @FinancialRadDeveloper, về cả hai điểm. Tôi sẽ xóa bình luận của mình. Cảm ơn vì đã nhận lỗi.
dreme

3
df [df ['ID']. Dupated () == True] Điều này sẽ trả về tất cả các bản sao
Hariprasad 19/11/18

12

Vì tôi không thể bình luận, do đó đăng dưới dạng một câu trả lời riêng

Để tìm các bản sao trên cơ sở nhiều cột, hãy đề cập đến mọi tên cột như bên dưới và nó sẽ trả về cho bạn tất cả các hàng trùng lặp đã đặt:

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

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

Điều này đã làm việc cho tôi


2
Bạn thực sự không phải thêm == True, .duplicated()đã trả về mảng bool.
Jakub Wagner

3

Bằng cách sử dụng logic khôn ngoan phần tử hoặc và đặt đối số take_last của phương thức trùng lặp gấu trúc thành True và False, bạn có thể lấy một tập hợp từ khung dữ liệu bao gồm tất cả các bản sao.

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

2

Đây có thể không phải là một giải pháp cho câu hỏi, nhưng để minh họa các ví dụ:

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)

Kết quả đầu ra:

   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

2

sort("ID")dường như không hoạt động ngay bây giờ, có vẻ như không được dùng nữa theo tài liệu sắp xếp , vì vậy hãy sử dụng sort_values("ID")thay thế để sắp xếp sau bộ lọc trùng lặp, như sau:

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

2

Đối với cơ sở dữ liệu của tôi được sao chép (keep = False) đã không hoạt động cho đến khi cột được sắp xếp.

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

1

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


4
Xin vui lòng, bạn có thể mở rộng câu trả lời của bạn với giải thích chi tiết hơn? Điều này sẽ rất hữu ích cho sự hiểu biết. Cảm ơn bạn!
vezunchik

Chào mừng bạn đến với Stack Overflow và cảm ơn sự đóng góp của bạn! Sẽ thật tốt nếu bạn có thể giải thích cho bạn câu trả lời. Ở đây bạn tìm thấy hướng dẫn Cách đưa ra câu trả lời hay . Cảm ơn!
David
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.