ปล่อยแถวที่ซ้ำกันทั้งหมดใน Python Pandas


160

pandas drop_duplicatesฟังก์ชั่นที่ดีสำหรับ "uniquifying" dataframe อย่างไรก็ตามหนึ่งในอาร์กิวเมนต์ของคำหลักที่จะผ่านคือtake_last=Trueหรือtake_last=Falseในขณะที่ฉันต้องการวางแถวทั้งหมดที่ซ้ำกันในส่วนย่อยของคอลัมน์ เป็นไปได้ไหม

    A   B   C
0   foo 0   A
1   foo 1   A
2   foo 1   B
3   bar 1   A

เป็นตัวอย่างที่ผมอยากจะวางแถวซึ่งตรงกับในคอลัมน์AและCดังนั้นนี้จะลดลงแถว 0 และ 1

คำตอบ:


235

สิ่งนี้ง่ายกว่ามากในแพนด้าตอนนี้ด้วยdrop_duplicatesและพารามิเตอร์ keep

import pandas as pd
df = pd.DataFrame({"A":["foo", "foo", "foo", "bar"], "B":[0,1,1,1], "C":["A","A","B","A"]})
df.drop_duplicates(subset=['A', 'C'], keep=False)

2
จะทำอย่างไรถ้าคอลัมน์ของฉันไม่มีป้ายกำกับชัดเจน? ฉันจะเลือกคอลัมน์ตามดัชนีได้อย่างไร
Hamman ซามูเอล

2
อาจจะdf.reindex(df.iloc[:,[0,2]].drop_duplicates(keep=False).index)?
เบ็น

5
คุณสามารถลองdf.drop_duplicates(subset=[df.columns[0:2]], keep = False)
seeiespi

68

เพียงแค่ต้องการเพิ่มคำตอบของ Ben ในdrop_duplicates :

keep : {'แรก', 'สุดท้าย', เท็จ}, เริ่มต้น 'แรก'

  • first: ปล่อยรายการที่ซ้ำกันยกเว้นการเกิดขึ้นครั้งแรก

  • last: ปล่อยรายการซ้ำยกเว้นการเกิดขึ้นครั้งสุดท้าย

  • เท็จ: วางรายการซ้ำทั้งหมด

ดังนั้นการตั้งค่าkeepเป็นเท็จจะให้คำตอบที่คุณต้องการ

DataFrame.drop_duplicates (* args, ** kwargs) ส่งคืน DataFrame โดยลบแถวที่ซ้ำกันออกไปเป็นทางเลือกโดยพิจารณาเฉพาะคอลัมน์บางคอลัมน์เท่านั้น

พารามิเตอร์: เซ็ตย่อย: เลเบลคอลัมน์หรือลำดับของเลเบลเป็นทางเลือกพิจารณาเฉพาะคอลัมน์บางอย่างสำหรับการระบุรายการที่ซ้ำกันโดยค่าเริ่มต้นใช้คอลัมน์ทั้งหมดที่เก็บไว้: {'แรก', 'สุดท้าย', เท็จ} เริ่มต้น 'แรก': ซ้ำกันยกเว้น สำหรับการเกิดขึ้นครั้งแรก last: ปล่อยรายการซ้ำยกเว้นการเกิดขึ้นครั้งสุดท้าย เท็จ: วางรายการซ้ำทั้งหมด take_last: ไม่สนับสนุน inplace: บูลีน, ค่าเริ่มต้น False ไม่ว่าจะวางที่ซ้ำกันในสถานที่หรือเพื่อกลับคัดลอก cols: kwargs อาร์กิวเมนต์เฉพาะของชุดย่อย [คัดค้าน] ผลตอบแทน: deduplicated: DataFrame


26

หากคุณต้องการเก็บผลลัพธ์ไว้ในชุดข้อมูลอื่น:

df.drop_duplicates(keep=False)

หรือ

df.drop_duplicates(keep=False, inplace=False)

หากจำเป็นต้องอัปเดตชุดข้อมูลเดียวกัน:

df.drop_duplicates(keep=False, inplace=True)

ตัวอย่างข้างต้นจะลบรายการที่ซ้ำกันทั้งหมดและเก็บไว้หนึ่งรายการที่คล้ายกับDISTINCT *ใน SQL


12

ใช้groupbyและfilter

import pandas as pd
df = pd.DataFrame({"A":["foo", "foo", "foo", "bar"], "B":[0,1,1,1], "C":["A","A","B","A"]})
df.groupby(["A", "C"]).filter(lambda df:df.shape[0] == 1)

5

ที่จริงแล้วปล่อยแถวที่ 0 และ 1 เท่านั้นที่ต้องการ (การสังเกตใด ๆ ที่มีการจับคู่ A และ C จะถูกเก็บไว้):

In [335]:

df['AC']=df.A+df.C
In [336]:

print df.drop_duplicates('C', take_last=True) #this dataset is a special case, in general, one may need to first drop_duplicates by 'c' and then by 'a'.
     A  B  C    AC
2  foo  1  B  fooB
3  bar  1  A  barA

[2 rows x 4 columns]

แต่ฉันสงสัยว่าสิ่งที่คุณต้องการคือ (การสังเกตหนึ่งที่มีการจับคู่ A และ C จะถูกเก็บไว้):

In [337]:

print df.drop_duplicates('AC')
     A  B  C    AC
0  foo  0  A  fooA
2  foo  1  B  fooB
3  bar  1  A  barA

[3 rows x 4 columns]

แก้ไข:

ตอนนี้มันชัดเจนมากขึ้นดังนั้น:

In [352]:
DG=df.groupby(['A', 'C'])   
print pd.concat([DG.get_group(item) for item, value in DG.groups.items() if len(value)==1])
     A  B  C
2  foo  1  B
3  bar  1  A

[2 rows x 3 columns]

1
หากนั่นคือสิ่งที่ฉันต้องการฉันจะใช้df.drop_duplicates(['A','C'])เป็นค่าเริ่มต้นทำให้การสังเกตหนึ่งครั้งใช้ครั้งแรกหรือครั้งสุดท้ายตามที่ฉันพูดถึงในคำถาม - แม้ว่าฉันเพิ่งรู้ว่าฉันมีคำหลักผิดเมื่อฉันเขียนจากหน่วยความจำ สิ่งที่ฉันต้องการคือการวางแถวทั้งหมดที่เหมือนกันในคอลัมน์ที่น่าสนใจ (A และ C ในข้อมูลตัวอย่าง)
Jamie Bull

0

ลองสิ่งต่าง ๆ เหล่านี้

df = pd.DataFrame({"A":["foo", "foo", "foo", "bar","foo"], "B":[0,1,1,1,1], "C":["A","A","B","A","A"]})

>>>df.drop_duplicates( "A" , keep='first')

หรือ

>>>df.drop_duplicates( keep='first')

หรือ

>>>df.drop_duplicates( keep='last')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.