ค้นหาแถวที่ซ้ำกันทั้งหมดรวมถึง "องค์ประกอบที่มีตัวห้อยเล็กกว่า"


112

R duplicatedส่งคืนเวกเตอร์ที่แสดงว่าแต่ละองค์ประกอบของเวกเตอร์หรือเฟรมข้อมูลซ้ำกันขององค์ประกอบที่มีตัวห้อยเล็กกว่า ดังนั้นหากแถวที่ 3, 4 และ 5 ของเฟรมข้อมูล 5 แถวเหมือนกันduplicatedจะให้เวกเตอร์

FALSE, FALSE, FALSE, TRUE, TRUE

แต่ในกรณีนี้ฉันอยากจะได้จริงๆ

FALSE, FALSE, TRUE, TRUE, TRUE

นั่นคือฉันต้องการทราบว่าแถวนั้นซ้ำกันหรือไม่โดยแถวที่มีตัวห้อยใหญ่กว่าด้วย

คำตอบ:


129

duplicatedมีfromLastข้อโต้แย้ง ส่วน "ตัวอย่าง" จะ?duplicatedแสดงวิธีการใช้งาน เพียงแค่โทรduplicatedสองครั้งครั้งด้วยfromLast=FALSEและครั้งเดียวกับและใช้แถวที่มีอย่างใดอย่างหนึ่งfromLast=TRUETRUE


การแก้ไขล่าช้า: คุณไม่ได้ให้ตัวอย่างที่ทำซ้ำได้ดังนั้นนี่คือภาพประกอบที่กรุณาสนับสนุนโดย @jbaums

vec <- c("a", "b", "c","c","c") 
vec[duplicated(vec) | duplicated(vec, fromLast=TRUE)]
## [1] "c" "c" "c"

แก้ไข: และตัวอย่างสำหรับกรณีของ data frame:

df <- data.frame(rbind(c("a","a"),c("b","b"),c("c","c"),c("c","c")))
df[duplicated(df) | duplicated(df, fromLast=TRUE), ]
##   X1 X2
## 3  c  c
## 4  c  c

3
เดี๋ยวก่อนฉันเพิ่งทำการทดสอบและพบว่าฉันคิดผิด: x <- c(1:9, 7:10, 5:22); y <- c(letters, letters[1:5]); test <- data.frame(x, y); test[duplicated(test$x) | duplicated(test$x, fromLast=TRUE), ]ส่งคืนสำเนาทั้งสามของเขาเป็น 7, 8 และ 9 ทำไมถึงได้ผล?
JoeM05

1
เนื่องจากคนตรงกลางถูกจับไม่ว่าคุณจะเริ่มจากท้ายหรือจากด้านหน้า ยกตัวอย่างเช่นduplicated(c(1,1,1))VS duplicated(c(1,1,1,), fromLast = TRUE)ให้และc(FALSE,TRUE,TRUE) c(TRUE,TRUE,FALSE)ค่ากลางอยู่TRUEในทั้งสองกรณี การของทั้งสองเวกเตอร์ให้| c(TRUE,TRUE,TRUE)
Brandon

34

คุณจะต้องรวบรวมชุดของduplicatedค่าใช้แล้วทดสอบด้วยunique %in%เช่นเคยปัญหาตัวอย่างจะทำให้กระบวนการนี้มีชีวิตชีวา

> vec <- c("a", "b", "c","c","c")
> vec[ duplicated(vec)]
[1] "c" "c"
> unique(vec[ duplicated(vec)])
[1] "c"
>  vec %in% unique(vec[ duplicated(vec)]) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

ตกลง. อาจทำให้การประมวลผลช้าลง แต่ไม่น่าจะทำให้ช้าลงมากนัก
IRTFM

ค่อนข้างจริง. OP ไม่ได้เสนอตัวอย่างข้อมูลเพื่อทดสอบแถวที่ "เคยซ้ำกัน" ในดาต้าเฟรม ผมคิดว่าคำแนะนำของฉันของการใช้duplicated, uniqueและ%in%ได้อย่างง่ายดายทั่วไปเพื่อ dataframe ถ้าคนใดคนหนึ่งไปก่อนpasteแต่ละแถวด้วยตัวคั่นที่ผิดปกติ (คำตอบที่ยอมรับได้ดีกว่า)
IRTFM

4

แถวที่ซ้ำกันในดาต้าเฟรมสามารถหาได้ด้วยdplyrการทำ

df = bind_rows(iris, head(iris, 20)) # build some test data
df %>% group_by_all() %>% filter(n()>1) %>% ungroup()

เพื่อยกเว้นบางคอลัมน์ group_by_at(vars(-var1, -var2))สามารถใช้แทนในการจัดกลุ่มข้อมูลได้

หากดัชนีแถวไม่ใช่แค่ข้อมูลที่จำเป็นจริงๆคุณสามารถเพิ่มดัชนีเหล่านี้ก่อนได้ใน:

df %>% add_rownames %>% group_by_at(vars(-rowname)) %>% filter(n()>1) %>% pull(rowname)

1
ใช้งานn()ได้ดี อย่าลืมยกเลิกการจัดกลุ่มดาต้าเฟรมที่เป็นผลลัพธ์
qwr

@qwr ฉันได้ปรับคำตอบเพื่อยกเลิกการจัดกลุ่มผลลัพธ์
Holger Brandl

3

ฉันมีคำถามเหมือนกันและถ้าฉันจำไม่ผิดนี่ก็เป็นคำตอบเช่นกัน

vec[col %in% vec[duplicated(vec$col),]$col]

Dunno อันไหนเร็วกว่า แต่ชุดข้อมูลที่ฉันใช้อยู่นั้นไม่ใหญ่พอที่จะทำการทดสอบซึ่งทำให้เกิดช่องว่างของเวลาที่สำคัญ


1
คำตอบนี้ดูเหมือนจะใช้vecทั้งเป็นเวกเตอร์อะตอมและเป็นดาต้าเฟรม ฉันสงสัยว่าด้วย datframe จริงมันจะล้มเหลว
IRTFM

2

นี่คือโซลูชันของ @Joshua Ulrich เป็นฟังก์ชัน รูปแบบนี้ช่วยให้คุณสามารถใช้รหัสนี้ในลักษณะเดียวกับที่คุณจะใช้ duplicated ():

allDuplicated <- function(vec){
  front <- duplicated(vec)
  back <- duplicated(vec, fromLast = TRUE)
  all_dup <- front + back > 0
  return(all_dup)
}

โดยใช้ตัวอย่างเดียวกัน:

vec <- c("a", "b", "c","c","c") 
allDuplicated(vec) 
[1] FALSE FALSE  TRUE  TRUE  TRUE

0

หากคุณสนใจว่าแถวใดที่ซ้ำกันสำหรับบางคอลัมน์คุณสามารถใช้วิธีplyr :

ddply(df, .(col1, col2), function(df) if(nrow(df) > 1) df else c())

การเพิ่มตัวแปร count ด้วยdplyr :

df %>% add_count(col1, col2) %>% filter(n > 1)  # data frame
df %>% add_count(col1, col2) %>% select(n) > 1  # logical vector

สำหรับแถวที่ซ้ำกัน (พิจารณาจากคอลัมน์ทั้งหมด):

df %>% group_by_all %>% add_tally %>% ungroup %>% filter(n > 1)
df %>% group_by_all %>% add_tally %>% ungroup %>% select(n) > 1

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


0

ฉันมีปัญหาที่คล้ายกัน แต่ฉันต้องการระบุแถวที่ซ้ำกันตามค่าในคอลัมน์เฉพาะ ฉันคิดโซลูชันdplyrต่อไปนี้:

df <- df %>% 
  group_by(Column1, Column2, Column3) %>% 
  mutate(Duplicated = case_when(length(Column1)>1 ~ "Yes",
                            TRUE ~ "No")) %>%
  ungroup()

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

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