mengidentifikasi dan menandai baris duplikat di r

11

Saya ingin mengidentifikasi dan menandai baris duplikat berdasarkan 2 kolom. Saya ingin membuat pengidentifikasi unik untuk setiap duplikat jadi saya tahu bukan hanya barisnya adalah duplikat, tetapi baris mana yang merupakan duplikat dengannya. Saya memiliki kerangka data yang terlihat seperti di bawah ini dengan beberapa pasangan item duplikat (saat cocok dan duduk) dan pasangan lain yang tidak digandakan. Sementara pasangan barang digandakan, informasi yang dikandungnya unik (misalnya, satu baris akan memiliki nilai dalam Value1 untuk 1 baris, tetapi bukan Value2 dan Nilai 3, baris kedua atau 'duplikat' akan memiliki angka untuk Value2 dan Value3 saja bukan Value1)

kerangka data saat ini

     value1 value2 value3 fit   sit  
[1,] "1"    NA     NA     "it1" "it2"
[2,] NA     "3"    "2"    "it2" "it1"
[3,] "2"    "3"    "4"    "it3" "it4"
[4,] NA     NA     NA     "it4" "it3"
[5,] "5"    NA     NA     "it5" "it6"
[6,] NA     NA     "2"    "it6" "it5"
[7,] NA     "4"    NA     "it7" "it9"

kode untuk menghasilkan contoh dataframe

value1<-c(1,NA,2,NA,5,NA,NA)
value2<-c(NA,3,3,NA,NA,NA, 4)
value3<-c(NA,2,4,NA,NA,2, NA)
fit<-c("it1","it2","it3","it4", "it5", "it6","it7")
sit<-c("it2","it1","it4","it3", "it6", "it5", "it9")
df.now<-cbind(value1,value2,value3, fit, sit)

yang saya inginkan adalah mengonversinya menjadi kerangka data yang terlihat seperti ini:

bingkai data yang diinginkan

     val1 val2 val3 it1   it2  
[1,] "1"  "3"  "2"  "it1" "it2"
[2,] "2"  "3"  "4"  "it3" "it4"
[3,] "5"  NA   "2"  "it5" "it6"
[4,] NA   "4"  NA   "it7" "it9"

Saya berpikir untuk melakukan langkah-langkah berikut: 1. membuat variabel baru menggunakan fit dan duduk dengan item terendah dan item tertinggi untuk mengidentifikasi pasangan duplikat 2. mengidentifikasi pasangan item duplikat 3. menggunakan ifelse untuk memilih dan mengisi informasi unik.

Saya tahu bagaimana melakukan langkah 1 dan 3, tetapi saya terjebak pada langkah 2. Saya pikir apa yang perlu saya lakukan tidak hanya mengidentifikasi duplikat BENAR / SALAH, tetapi mungkin memiliki kolom dengan pengidentifikasi unik untuk setiap pasangan item seperti ini (ada 2 baris tambahan karena langkah saya 1):

     value1 value2 value3 fit   sit   lit   hit    dup
[1,] "1"    NA     NA     "it1" "it2" "it1" "it2"   1
[2,] NA     "3"    "2"    "it2" "it1" "it1" "it2"   1
[3,] "2"    "3"    "4"    "it3" "it4" "it3" "it4"   2
[4,] NA     NA     NA     "it4" "it3" "it3" "it4"   2
[5,] "5"    NA     NA     "it5" "it6" "it5" "it6"   3
[6,] NA     NA     "2"    "it6" "it5" "it5" "it6"   3
[7,] NA     "4"    NA     "it7" "it9" "it7" "it9"   NA

Saya tidak yakin bagaimana melakukan ini.

Apa yang saya minta adalah bantuan dengan langkah 2 atau mungkin ada cara yang lebih baik untuk menyelesaikannya daripada langkah-langkah yang saya uraikan.

Heather Clark
sumber

Jawaban:

6

Satu dplyropsi bisa:

df.now %>%
 group_by(pair = paste(pmax(fit, sit), pmin(fit, sit), sep = "_")) %>%
 summarise_at(vars(starts_with("value")), ~ ifelse(all(is.na(.)), 
                                                   NA,
                                                   first(na.omit(.))))

  pair    value1 value2 value3
  <chr>    <dbl>  <dbl>  <dbl>
1 it2_it1      1      3      2
2 it4_it3      2      3      4
3 it6_it5      5     NA      2
4 it9_it7     NA      4     NA

Dan jika Anda juga membutuhkan pasangan dalam kolom individual, maka dengan penambahan tidyryang dapat Anda lakukan:

df.now %>%
 group_by(pair = paste(pmax(fit, sit), pmin(fit, sit), sep = "_")) %>%
 summarise_at(vars(starts_with("value")), ~ ifelse(all(is.na(.)), 
                                                   NA,
                                                   first(na.omit(.)))) %>%
 separate(pair, into = c("fit", "hit"), sep = "_", remove = FALSE)

  pair    fit   hit   value1 value2 value3
  <chr>   <chr> <chr>  <dbl>  <dbl>  <dbl>
1 it2_it1 it2   it1        1      3      2
2 it4_it3 it4   it3        2      3      4
3 it6_it5 it6   it5        5     NA      2
4 it9_it7 it9   it7       NA      4     NA
tmfmnk
sumber
Terima kasih! Ini bekerja dengan baik. Saya menghargai menambahkan opsi untuk memisahkan item.
Heather Clark
3

Gunakan !duplicated()setelah sorting.

df.now[!duplicated(t(apply(df.now[, c("fit", "sit")], 1, sort))), ]
#       value1 value2 value3 fit   sit  
# [1,] "1"    NA     NA     "it1" "it2"
# [2,] "2"    "3"    "4"    "it3" "it4"
# [3,] "5"    NA     NA     "it5" "it6"
# [4,] NA     "4"    NA     "it7" "it9"
jay.sf
sumber
Terima kasih atas respon yang cepat. Namun, solusi ini menghapus informasi yang perlu saya simpan. Saya ingin menggabungkan informasi dari 3 kolom nilai yang ditemukan di 2 baris pasangan item yang sama. Beri tahu saya jika ini tidak jelas
Heather Clark
2

Menggunakan melt/dcastdaridata.table

library(data.table)
dcast(melt(setDT(df.now)[, c('fit1', 'sit1') := .(pmin(fit, sit), 
    pmax(fit, sit))], measure = patterns("^value"), na.rm = TRUE),
     fit1 + sit1 ~ variable, value.var = 'value')
#   fit1 sit1 value1 value2 value3
#1:  it1  it2      1      3      2
#2:  it3  it4      2      3      4
#3:  it5  it6      5     NA      2
#4:  it7  it9     NA      4     NA

data

df.now <- data.frame(value1,value2,value3, fit, sit, stringsAsFactors = FALSE)
akrun
sumber
2

data.tableOpsi lain :

library(data.table)
as.data.table(df.now)[, lapply(.SD, function(x) first(x[!is.na(x)])), 
    .(it1=pmin(fit, sit), it2=pmax(fit, sit)), 
    .SDcols=value1:value3]

keluaran:

   it1 it2 value1 value2 value3
1: it1 it2      1      3      2
2: it3 it4      2      3      4
3: it5 it6      5   <NA>      2
4: it7 it9   <NA>      4   <NA>
chinsoon12
sumber
1

Inilah upaya saya menggunakan data.table. Data Anda dipanggil mydf. Pertama, saya mengurutkan fitdan situntuk setiap baris dan membuat variabel baru group,. Kemudian, untuk setiap grup, saya mengurutkan nilai dalam tiga kolom nilai (yaitu, value1, value2, dan value3). Akhirnya, saya mengekstrak baris pertama untuk setiap grup.

library(data.table)

mydt <- setDT(mydf)[, group := paste(sort(.SD), collapse = "_"),
                    .SD = c("fit", "sit"), by = 1:nrow(mydf)][,
                        c("value1", "value2", "value3") := lapply(.SD, sort),
                        .SDcols = value1:value3, by = group][, .SD[1], by = group]

mydt[]

#     group value1 value2 value3 fit sit
#1: it1_it2      1      3      2 it1 it2
#2: it3_it4      2      3      4 it3 it4
#3: it5_it6      5     NA      2 it5 it6
#4: it7_it9     NA      4     NA it7 it9

DATA

mydf <- structure(list(value1 = c(1L, NA, 2L, NA, 5L, NA, NA), value2 = c(NA, 
3L, 3L, NA, NA, NA, 4L), value3 = c(NA, 2L, 4L, NA, NA, 2L, NA
), fit = c("it1", "it2", "it3", "it4", "it5", "it6", "it7"), 
sit = c("it2", "it1", "it4", "it3", "it6", "it5", "it9")), class = "data.frame", row.names = c(NA, 
-7L))
jazzurro
sumber
1

Ini juga dapat dilakukan menggunakan tidyr's pivot_longerdengan values_drop_na = TRUEdikombinasikan dengan pivot_wider:

library(tidyverse)

mydf %>%
   mutate(it1 = pmin(fit, sit), it2 = pmax(fit, sit)) %>%
   pivot_longer(cols = starts_with("value"), values_drop_na = TRUE) %>%
   pivot_wider(id_cols = c("it1", "it2"))

#> # A tibble: 4 x 5
#>   it1   it2   value1 value2 value3
#>   <chr> <chr>  <int>  <int>  <int>
#> 1 it1   it2        1      3      2
#> 2 it3   it4        2      3      4
#> 3 it5   it6        5     NA      2
#> 4 it7   it9       NA      4     NA

Data

mydf <- structure(list(value1 = c(1L, NA, 2L, NA, 5L, NA, NA), value2 = c(NA, 
3L, 3L, NA, NA, NA, 4L), value3 = c(NA, 2L, 4L, NA, NA, 2L, NA
), fit = c("it1", "it2", "it3", "it4", "it5", "it6", "it7"), 
sit = c("it2", "it1", "it4", "it3", "it6", "it5", "it9")), class = "data.frame", row.names = c(NA, 
-7L))
Joris Chau
sumber