ลบแถวที่ซ้ำกัน


152

ฉันอ่านCSVไฟล์ไปยัง data.frame R แล้ว บางแถวมีองค์ประกอบเดียวกันในคอลัมน์ใดคอลัมน์หนึ่ง ฉันต้องการลบแถวที่ซ้ำกันในคอลัมน์นั้น ตัวอย่างเช่น:

platform_external_dbus          202           16                     google        1
platform_external_dbus          202           16         space-ghost.verbum        1
platform_external_dbus          202           16                  localhost        1
platform_external_dbus          202           16          users.sourceforge        8
platform_external_dbus          202           16                    hughsie        1

ฉันต้องการแถวเดียวเหล่านี้เนื่องจากแถวอื่นมีข้อมูลเดียวกันในคอลัมน์แรก


3
คุณต้องการอันไหน แค่คนแรก? ในคำอื่น ๆ : คุณต้องการที่จะเก็บgoogleหรือlocalhostหรือhughsie?
Anthony Damico

มันไม่สำคัญสำหรับการวิเคราะห์ทางสถิติของฉันในส่วนนี้ ฉันพยายามเชื่อมโยงชื่อโครงการ (คอลัมน์แรก) จำนวนข้อบกพร่อง (คอลัมน์ที่สอง) และจำนวนองค์กรในโครงการ (คอลัมน์ที่สาม)
user1897691

3
เย็น. โยนคอลัมน์ที่ไม่จำเป็นออกมาและใช้หรือไม่ซ้ำใคร
Anthony Damico

คำตอบ:


186

เพียงแค่แยก data data ของคุณไปยังคอลัมน์ที่คุณต้องการจากนั้นใช้ฟังก์ชันที่ไม่ซ้ำกัน: D

# in the above example, you only need the first three columns
deduped.data <- unique( yourdata[ , 1:3 ] )
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out.

1
ดูเหมือนว่ามันจะทำงานได้อย่างสมบูรณ์แบบ คุณช่วยอธิบายให้ฉันฟังได้ว่าเกิดอะไรขึ้นกับ[,1:3]ส่วนของรหัสนั้น? ฉันใหม่กับ R ซึ่งเป็นเหตุผลที่ฉันถามสิ่งที่ฉันสามารถถือว่าเป็นคำถามที่ชัดเจนเท่านั้น
user1897691

6
@ user1897691 ทำเครื่องหมายว่าถูกต้องแล้ว;) ดูสิ่งนี้และถ้าคุณชอบให้ตรวจสอบtwotorials.com
Anthony Damico

3
โปรดทราบว่าการดำเนินการนี้จะลบคอลัมน์ทั้งหมดยกเว้นสามคอลัมน์แรก
GuillaumeL

186

สำหรับผู้ที่มาที่นี่เพื่อค้นหาคำตอบทั่วไปสำหรับการลบแถวที่ซ้ำกันให้ใช้!duplicated():

a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

duplicated(df)
[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE

> df[duplicated(df), ]
  a b
2 A 1
6 B 1
8 C 2

> df[!duplicated(df), ]
  a b
1 A 1
3 A 2
4 B 4
5 B 1
7 C 2

คำตอบจาก: การลบแถวที่ซ้ำซ้อนออกจากกรอบข้อมูล R


ฉันต้องการสร้าง varibale ใหม่ที่ตั้งค่าสถานะหากมีการซ้ำซ้อนกับตัวแปรบางตัวเช่น df $ ซ้ำกัน <- ifelse (ค่าแถวนี้ในคอลัมน์ a == ค่าแถวก่อนหน้าในคอลัมน์ a, 1, 0)
jacob

@jacob ดูคำถามนี้stackoverflow.com/questions/12495345/…
dpel

2
นี่จะช่วยรักษาค่าที่ปรากฏครั้งแรกและลบส่วนที่เหลือของรายการซ้ำใช่ไหม หรือจะลบค่าแบบสุ่ม?
News_is_Selection_Bias

@alphabetagamma ใช่มันเก็บค่าปรากฏตัวครั้งแรก
Mehdi Nellen

2
หากคุณสนใจซ้ำซ้อนในบางคอลัมน์พูด cols 1 และ 2 เราสามารถใช้df[!duplicated(df[, 1:2])]
qwr

82

ฟังก์ชั่นdistinct()ในdplyrแพคเกจทำการลบที่ซ้ำกันโดยพลการไม่ว่าจะมาจากคอลัมน์ / ตัวแปรเฉพาะ (เช่นในคำถามนี้) หรือพิจารณาคอลัมน์ / ตัวแปรทั้งหมด dplyrเป็นส่วนหนึ่งของtidyverseเป็นส่วนหนึ่งของ

ข้อมูลและแพ็คเกจ

library(dplyr)
dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2))

ลบแถวที่ซ้ำกันในคอลัมน์เฉพาะ (เช่นคอลัมน์a)

โปรดทราบว่า.keep_all = TRUEเก็บคอลัมน์ทั้งหมดไว้มิฉะนั้นaจะคงคอลัมน์ไว้เท่านั้น

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

ลบแถวที่ซ้ำกันของแถวอื่น:

distinct(dat)

  a b
1 1 A
2 2 B
3 1 C
4 2 D

คำตอบที่ดีโดยวิธีการ.keep_allสำหรับการว่าจะเก็บคอลัมน์ทั้งหมดที่ไม่ได้รับการผสมกับในkeep pandas
Jason Goal

28

data.tableแพคเกจยังมีuniqueและduplicatedวิธีการของมันเองด้วยคุณสมบัติเพิ่มเติมบางอย่าง

ทั้งวิธีunique.data.tableการและduplicated.data.tableมีbyข้อโต้แย้งเพิ่มเติมซึ่งช่วยให้คุณสามารถส่งผ่านcharacterหรือintegerเวกเตอร์ของชื่อคอลัมน์หรือตำแหน่งของพวกเขาตามลำดับ

library(data.table)
DT <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

unique(DT, by = "id")
#    id val
# 1:  1  10
# 2:  2  10

duplicated(DT, by = "id")
# [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

คุณสมบัติที่สำคัญอีกประการของวิธีการเหล่านี้คือประสิทธิภาพที่เพิ่มขึ้นอย่างมากสำหรับชุดข้อมูลขนาดใหญ่

library(microbenchmark)
library(data.table)
set.seed(123)
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10))
DT <- copy(DF)
setDT(DT)

microbenchmark(unique(DF), unique(DT))
# Unit: microseconds
#       expr       min         lq      mean    median        uq       max neval cld
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18   100   b
# unique(DT)   746.855   776.6145  2201.657   864.932   919.489  55986.88   100  a 


microbenchmark(duplicated(DF), duplicated(DT))
# Unit: microseconds
#           expr       min         lq       mean     median        uq        max neval cld
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170   100   b
# duplicated(DT)   551.982   558.2215   851.0246   639.9795   663.658   5805.243   100  a 

7

นอกจากนี้คุณยังสามารถใช้dplyrของdistinct()ฟังก์ชั่น! มันมีแนวโน้มที่จะมีประสิทธิภาพมากกว่าทางเลือกอื่นโดยเฉพาะถ้าคุณมีข้อสังเกตมากมาย

distinct_data <- dplyr::distinct(yourdata)

1
นี่เป็นคำตอบเดียวกับคำตอบของ Sam Firke แต่มีรายละเอียดน้อยกว่า
qwr

6

คำตอบทั่วไปสามารถเป็นตัวอย่างได้:

df <-  data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6))))



new_df <- df[-which(duplicated(df)), ]

เอาท์พุท:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
ระมัดระวังเมื่อใช้-whichสิ่งนี้จะนำไปสู่ข้อผิดพลาดหากไม่มีการซ้ำซ้อนการใช้df[!(duplicated(df)), ]อาจปลอดภัยกว่า
เจสันโกล

5

ด้วยsqldf:

# Example by Mehdi Nellen
a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

สารละลาย:

 library(sqldf)
    sqldf('SELECT DISTINCT * FROM df')

เอาท์พุท:

  a b
1 A 1
2 A 2
3 B 4
4 B 1
5 C 2

นี่มีค่าใช้จ่ายในการตั้งค่าฐานข้อมูล SQL ทั้งหมด cran.r-project.org/web/packages/sqldf/index.html
qwr

คุณหมายถึงอะไรโดยตั้งค่าฐานข้อมูล SQL ทั้งหมด นั่นคือหนึ่งในข้อได้เปรียบหลัก: 'กับ sqldf ผู้ใช้จะได้รับอิสระจากการทำสิ่งต่อไปนี้ซึ่งทั้งหมดจะทำโดยอัตโนมัติ: การตั้งค่าฐานข้อมูลการเขียนคำสั่งสร้างตารางซึ่งกำหนดแต่ละตารางการนำเข้าและส่งออกจากฐานข้อมูล ' มันไม่ใช่ทางออกที่ดีที่สุด แต่มีประโยชน์สำหรับผู้ที่คุ้นเคยกับ SQL
mpalanco

3

หรือคุณสามารถซ้อนข้อมูลใน cols 4 และ 5 เป็นแถวเดียวด้วยtidyr:

library(tidyr)
df %>% nest(V4:V5)

# A tibble: 1 × 4
#                      V1    V2    V3             data
#                  <fctr> <int> <int>           <list>
#1 platform_external_dbus   202    16 <tibble [5 × 2]>

ตอนนี้สำเนาซ้ำซ้อน 2 และ 3 จะถูกลบออกสำหรับการวิเคราะห์ทางสถิติ แต่คุณได้เก็บข้อมูล col 4 และ 5 ไว้ในระดับเล็กน้อยและสามารถกลับไปที่กรอบข้อมูลเดิมได้ทุกunnest()เมื่อ


1

ลบแถวที่ซ้ำกันของ dataframe

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

ในชุดข้อมูลนี้ไม่มีแถวที่ซ้ำกันเดียวดังนั้นจึงส่งคืนจำนวนแถวเดียวกันกับใน mydata



เอาแถวที่ซ้ำออกโดยยึดตามตัวแปรตัวเดียว

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using carb variable
distinct(mydata,carb, .keep_all= TRUE)

ฟังก์ชัน. keep_all ใช้เพื่อเก็บรักษาตัวแปรอื่น ๆ ทั้งหมดในเฟรมข้อมูลเอาท์พุท



เอาแถวที่ซ้ำออกโดยยึดตามตัวแปรหลายตัว

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using cyl and vs variables
distinct(mydata, cyl,vs, .keep_all= TRUE)

ฟังก์ชัน. keep_all ใช้เพื่อเก็บรักษาตัวแปรอื่น ๆ ทั้งหมดในเฟรมข้อมูลเอาท์พุท

(จาก: http://www.datasciencemadesimple.com/remove-duplicate-rows-r-using-dplyr-distinct-function/ )


0

ปัญหานี้สามารถแก้ไขได้โดยเลือกแถวแรกจากแต่ละกลุ่มที่กลุ่มเป็นคอลัมน์ตามที่เราต้องการเลือกค่าที่ไม่ซ้ำกัน (ในตัวอย่างที่แชร์เป็นเพียงคอลัมน์ที่ 1)

ใช้ฐาน R:

subset(df, ave(V2, V1, FUN = seq_along) == 1)

#                      V1  V2 V3     V4 V5
#1 platform_external_dbus 202 16 google  1

ใน dplyr

library(dplyr)
df %>% group_by(V1) %>% slice(1L)

หรือการใช้ data.table

library(data.table)
setDT(df)[, .SD[1L], by = V1]

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

ข้อมูล

df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
.Label = "platform_external_dbus", class = "factor"), 
V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
"hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, -5L))

0

นี่คือง่ายมากรวดเร็ว dplyrtidyวิธีแก้ปัญหาที่และมีประสิทธิภาพ:

ลบแถวที่เหมือนกันทั้งหมด:

library(dplyr)
iris %>% 
  distinct(.keep_all = TRUE)

ลบแถวที่เหมือนกันในคอลัมน์บางคอลัมน์เท่านั้น:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.