xác định và đánh dấu các hàng trùng lặp trong r


11

Tôi muốn xác định và đánh dấu các hàng trùng lặp dựa trên 2 cột. Tôi muốn tạo một mã định danh duy nhất cho mỗi bản sao để tôi biết không chỉ hàng đó là bản sao mà còn là hàng trùng lặp. Tôi có một khung dữ liệu trông giống như bên dưới với một số cặp mục trùng lặp (vừa vặn và ngồi) và các cặp khác không bị trùng lặp. Mặc dù các cặp mục được sao chép, thông tin chúng chứa là duy nhất (ví dụ: một hàng sẽ có giá trị trong Value1 cho 1 hàng, nhưng không phải là Value2 và Value 3, hàng thứ hai hoặc 'trùng lặp' sẽ có các số cho Value2 và Value3 không phải giá trị1)

khung dữ liệu hiện tại

     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"

mã để tạo dataframe ví dụ

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)

những gì tôi muốn là chuyển đổi nó thành một khung dữ liệu trông như thế này:

khung dữ liệu mong muốn

     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"

Tôi đã nghĩ đến việc thực hiện các bước sau: 1. tạo các biến mới bằng cách sử dụng fit và ngồi với mục thấp nhất và các mục cao nhất để xác định các cặp trùng lặp 2. xác định các cặp mục trùng lặp 3. sử dụng ifelse để chọn và điền thông tin duy nhất.

Tôi biết cách thực hiện bước 1 và 3, nhưng bị kẹt ở bước 2. Tôi nghĩ rằng điều tôi cần làm không chỉ là xác định trùng lặp TRUE / FALSE, mà có lẽ có một cột với một mã định danh duy nhất cho mỗi cặp vật phẩm như thế này (có là 2 hàng thừa vì bước 1 của tôi):

     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

Tôi không chắc chắn làm thế nào để làm điều này.

Những gì tôi đang yêu cầu là giúp đỡ với bước 2 hoặc có lẽ có một cách tốt hơn để giải quyết nó hơn các bước tôi đã vạch ra.

Câu trả lời:


6

Một dplyrlựa chọn có thể là:

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

Và nếu bạn cũng cần các cặp trong các cột riêng lẻ, thì với việc thêm tidyrbạn có thể làm:

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

Cảm ơn bạn! Điều này hoạt động tốt. Tôi đánh giá cao việc thêm vào tùy chọn để tách các mục.
Heather Clark

3

Sử dụng !duplicated()sau khi 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"

Cảm ơn bạn đã phản hồi nhanh chóng. Tuy nhiên, giải pháp này xóa thông tin tôi cần giữ. Tôi muốn kết hợp thông tin từ 3 cột giá trị được tìm thấy trên 2 hàng của cùng một cặp mục. Hãy cho tôi biết nếu điều này không rõ ràng
Heather Clark

2

Sử dụng melt/dcasttừdata.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

dữ liệu

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

2

Một data.tablelựa chọn khác :

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]

đầu ra:

   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>

1

Đây là nỗ lực của tôi bằng cách sử dụng data.table. Dữ liệu của bạn được gọi mydf. Đầu tiên, tôi sắp xếp fitsitcho mỗi hàng và tạo một biến mới , group. Sau đó, với mỗi nhóm, tôi đã sắp xếp các giá trị trong ba cột giá trị (nghĩa là value1, value2 và value3). Cuối cùng, tôi trích xuất hàng đầu tiên cho mỗi nhóm.

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

DỮ LIỆU

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))

1

Đây cũng có thể được thực hiện bằng tidyr's pivot_longervới values_drop_na = TRUEkết hợp với 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

Dữ liệu

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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.