Menemukan SEMUA baris duplikat, termasuk "elemen dengan subskrip yang lebih kecil"

111

R duplicatedmengembalikan vektor yang menunjukkan apakah setiap elemen dari vektor atau bingkai data adalah duplikat elemen dengan subskrip yang lebih kecil. Jadi jika baris 3, 4, dan 5 dari data frame 5 baris adalah sama, duplicatedsaya akan memberikan vektornya

FALSE, FALSE, FALSE, TRUE, TRUE

Tetapi dalam hal ini saya sebenarnya ingin mendapatkan

FALSE, FALSE, TRUE, TRUE, TRUE

yaitu, saya ingin tahu apakah sebuah baris diduplikasi oleh baris dengan subskrip yang lebih besar juga.

Lauren Samuels
sumber

Jawaban:

128

duplicatedmemiliki fromLastargumen. Bagian "Contoh" ?duplicatedmenunjukkan cara menggunakannya. Panggil saja duplicateddua kali, sekali dengan fromLast=FALSEdan sekali dengan fromLast=TRUEdan ambil baris di mana saja TRUE.


Beberapa Edit terlambat: Anda tidak memberikan contoh yang dapat direproduksi, jadi inilah ilustrasi yang disumbangkan oleh @jbaums

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

Edit: Dan contoh untuk kasus bingkai data:

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
Joshua Ulrich
sumber
3
Tunggu, saya baru saja menjalankan tes dan menemukan bahwa saya salah: 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), ]Mengembalikan ketiganya salinan 7, 8, dan 9. Mengapa itu berhasil?
JoeM05
1
Karena yang di tengah ditangkap tidak peduli apakah Anda mulai dari akhir atau dari depan. Misalnya, duplicated(c(1,1,1))vs duplicated(c(1,1,1,), fromLast = TRUE)memberi c(FALSE,TRUE,TRUE)dan c(TRUE,TRUE,FALSE). Nilai tengah TRUEdalam kedua kasus. Pengambilan |kedua vektor memberi c(TRUE,TRUE,TRUE).
Brandon
34

Anda perlu mengumpulkan kumpulan duplicatednilai, menerapkan unique, dan kemudian mengujinya dengan %in%. Seperti biasa, masalah sampel akan membuat proses ini menjadi hidup.

> 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
sumber
Setuju. Bahkan mungkin memperlambat pemrosesan tetapi tidak mungkin memperlambatnya terlalu banyak.
IRTFM
Benar sekali. OP tidak menawarkan contoh data untuk menguji baris yang "pernah digandakan" dalam kerangka data. Saya pikir saran saya untuk menggunakan duplicated, uniquedan %in%dapat dengan mudah digeneralisasikan ke kerangka data jika seseorang pertama kali pastesetiap baris dengan karakter pemisah yang tidak biasa. (Jawaban yang diterima lebih baik.)
IRTFM
3

Saya memiliki pertanyaan yang sama , dan jika saya tidak salah, ini juga sebuah jawaban.

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

Entah mana yang lebih cepat, meskipun, kumpulan data yang saya gunakan saat ini tidak cukup besar untuk melakukan pengujian yang menghasilkan kesenjangan waktu yang signifikan.

François M.
sumber
1
Jawaban ini tampaknya menggunakan veckeduanya sebagai vektor atom dan sebagai kerangka data. Saya menduga bahwa dengan datframe yang sebenarnya itu akan gagal.
IRTFM
3

Baris duplikat dalam kerangka data dapat diperoleh dengan dplyrmelakukan

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

Untuk mengecualikan kolom tertentu group_by_at(vars(-var1, -var2))dapat digunakan untuk mengelompokkan data.

Jika indeks baris dan bukan hanya data yang benar-benar dibutuhkan, Anda dapat menambahkannya terlebih dahulu seperti pada:

df %>% add_rownames %>% group_by_at(vars(-rowname)) %>% filter(n()>1) %>% pull(rowname)
Holger Brandl
sumber
1
Penggunaan yang bagus n(). Jangan lupa untuk memisahkan dataframe yang dihasilkan.
qwr
@qwr Saya telah menyesuaikan jawaban untuk membatalkan grup hasilnya
Holger Brandl
2

Berikut adalah solusi @Joshua Ulrich sebagai fungsi. Format ini memungkinkan Anda untuk menggunakan kode ini dengan cara yang sama seperti Anda menggunakan duplikat ():

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

Menggunakan contoh yang sama:

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

Jika Anda tertarik pada baris mana yang diduplikasi untuk kolom tertentu, Anda dapat menggunakan pendekatan plyr :

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

Menambahkan variabel hitungan dengan dplyr :

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

Untuk baris duplikat (mempertimbangkan semua kolom):

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

Manfaat dari pendekatan ini adalah Anda dapat menentukan berapa banyak duplikat sebagai batas.

qwr
sumber
0

Saya memiliki masalah serupa tetapi saya perlu mengidentifikasi baris yang digandakan berdasarkan nilai di kolom tertentu. Saya datang dengan solusi dplyr berikut :

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

Kode mengelompokkan baris menurut kolom tertentu. Jika panjang grup lebih dari 1 kode menandai semua baris dalam grup sebagai duplikat. Setelah selesai, Anda dapat menggunakan Duplicatedkolom untuk memfilter, dll.

Adnan Hajizada
sumber