ฉันจะรับรายชื่อรายการที่ซ้ำกันทั้งหมดโดยใช้แพนด้าใน python ได้อย่างไร


129

ฉันมีรายการสินค้าที่น่าจะมีปัญหาในการส่งออก ฉันต้องการรับรายชื่อรายการที่ซ้ำกันเพื่อที่ฉันจะได้เปรียบเทียบด้วยตนเอง เมื่อฉันพยายามใช้วิธีการทำสำเนาของแพนด้ามันจะส่งกลับรายการที่ซ้ำกันครั้งแรกเท่านั้น มีวิธีรับรายการที่ซ้ำกันทั้งหมดไม่ใช่แค่รายการแรกหรือไม่?

ส่วนย่อยเล็ก ๆ ของชุดข้อมูลของฉันมีลักษณะดังนี้:

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 รายการและรายการอื่น ๆ ที่ซ้ำกันแทนที่จะเป็นรายการแรก ความช่วยเหลือใด ๆ ที่ได้รับการชื่นชมมากที่สุด


1
"รายการที่ซ้ำกัน" อาจหมายถึงสิ่งต่างๆ "ในกรณีของคุณคุณต้องการพิจารณารายการที่ซ้ำกันในคอลัมน์เดียวIDเท่านั้นไม่ใช่" แถวที่เหมือนกันในหลายคอลัมน์หรือทุกคอลัมน์ "
smci

คำตอบ:


170

วิธีที่ # 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: 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

11
วิธีที่ 2 สมบูรณ์แบบ! ขอบคุณมาก.
BigHandsome

4
วิธีที่ # 2 ล้มเหลว ("ไม่มีวัตถุที่จะเชื่อมต่อกัน") หากไม่มีการทำซ้ำ
CPBL

4
สิ่งที่ไม่g for _ ทำอะไร?
user77005

5
@ user77005 คุณอาจคิดออกแล้ว แต่เพื่อประโยชน์ของทุกคนมันอ่านดังนี้: g for (placeholder, g) in df.groupby('bla') if 'bla'; ขีดล่างเป็นสัญลักษณ์ทั่วไปสำหรับตัวยึดตำแหน่งของอาร์กิวเมนต์ที่หลีกเลี่ยงไม่ได้ซึ่งเราไม่ต้องการใช้มันเพื่ออะไรก็ตามในนิพจน์แลมบ์ดา
stucash

7
ต้องอัปเดตวิธี # 1: sortเลิกใช้งาน DataFrames เพื่อรองรับSO Q&Aอย่างใดอย่างหนึ่งsort_valuesหรือsort_index ที่เกี่ยวข้อง
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

3
บิงโกมีคำตอบ ดังนั้น: str หรือ str หรือบูลีน ... ตัวเลือก API แปลก ๆ 'all'จะเป็น IMO ที่มีเหตุผลและใช้งานง่ายมากขึ้น
Jarad

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

มันจะส่งคืนแถวที่ซ้ำกันทั้งหมดกลับมาให้คุณ

ตามเอกสาร :

เก็บ: {'first', 'last', False}, default 'first'

  • อันดับแรก: ทำเครื่องหมายรายการที่ซ้ำกันเป็น True ยกเว้นเหตุการณ์แรก
  • last: ทำเครื่องหมายรายการที่ซ้ำกันเป็น True ยกเว้นรายการสุดท้าย
  • เท็จ: ทำเครื่องหมายรายการที่ซ้ำกันทั้งหมดว่าเป็นจริง

@dreme สิ่งนี้ไม่ถูกต้องตามหลักไวยากรณ์และไม่ได้ผล ไม่ตรงกัน ']' และยังไม่ส่งคืนสิ่งที่ต้องการอีกด้วย มันสั้นกว่า แต่ผิด
FinancialRadDeveloper

อ๊ะคุณพูดถูก @FinancialRadDeveloper ทั้งสองประการ ฉันจะลบความคิดเห็นของฉัน ขอขอบคุณที่แจ้งข้อผิดพลาด
dreme

4
df [df ['ID']. duplicated () == True] สิ่งนี้จะส่งคืนรายการที่ซ้ำกันทั้งหมด
Hariprasad

12

เนื่องจากฉันไม่สามารถแสดงความคิดเห็นได้จึงโพสต์เป็นคำตอบแยกต่างหาก

หากต้องการค้นหารายการที่ซ้ำกันบนพื้นฐานของคอลัมน์มากกว่าหนึ่งคอลัมน์ให้ระบุชื่อทุกคอลัมน์ดังต่อไปนี้และจะส่งคืนชุดแถวที่ซ้ำกันทั้งหมดให้คุณ:

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

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

สิ่งนี้ได้ผลสำหรับฉัน


2
จริงๆแล้วคุณไม่จำเป็นต้องเพิ่ม== True, .duplicated()แล้วส่งกลับอาร์เรย์บูล
Jakub Wagner

3

การใช้ตรรกะเชิงองค์ประกอบหรือและการตั้งค่าอาร์กิวเมนต์ 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)
              ]

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

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

1

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


4
กรุณาช่วยเพิ่มคำตอบพร้อมคำอธิบายโดยละเอียดได้ไหม สิ่งนี้จะเป็นประโยชน์มากสำหรับการทำความเข้าใจ ขอบคุณ!
vezunchik

ยินดีต้อนรับสู่ Stack Overflow และขอขอบคุณสำหรับการสนับสนุนของคุณ! จะเป็นการดีถ้าคุณสามารถขยายคำตอบให้คุณได้ นี่คุณจะพบคำแนะนำวิธีที่จะให้คำตอบที่ดี ขอบคุณ!
David
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.