ระบุและทำเครื่องหมายแถวที่ซ้ำกันใน r


11

ฉันต้องการระบุและทำเครื่องหมายแถวที่ซ้ำกันโดยยึดตาม 2 คอลัมน์ ฉันต้องการสร้างตัวระบุที่ไม่ซ้ำกันสำหรับแต่ละรายการที่ซ้ำกันดังนั้นฉันจึงรู้ว่าไม่ใช่ว่าแถวนั้นซ้ำกัน แต่แถวใดที่ซ้ำกัน ฉันมี dataframe ที่มีลักษณะเหมือนด้านล่างพร้อมคู่รายการที่ซ้ำกันบางรายการ (แบบพอดีและแบบนั่ง) และคู่อื่น ๆ ที่ไม่ได้ทำซ้ำ ในขณะที่คู่ไอเท็มมีการทำซ้ำข้อมูลที่มีอยู่จะไม่ซ้ำกัน (เช่นหนึ่งแถวจะมีค่าใน Value1 สำหรับ 1 แถว แต่ไม่ใช่ Value2 และ Value 3 แถวที่สองหรือ 'ซ้ำ' จะมีตัวเลขสำหรับ Value2 และ Value3 เพียง ไม่ใช่ค่า 1)

dataframe ปัจจุบัน

     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"

รหัสเพื่อสร้างดาต้าเฟรมตัวอย่าง

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)

สิ่งที่ฉันต้องการคือการแปลงเป็น dataframe ที่มีลักษณะเช่นนี้:

dataframe ที่ต้องการ

     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"

ฉันกำลังคิดที่จะทำตามขั้นตอนต่อไปนี้: 1. สร้างตัวแปรใหม่โดยใช้พอดีและนั่งกับรายการต่ำสุดและรายการสูงสุดเพื่อระบุคู่ที่ซ้ำกัน 2. ระบุคู่ของรายการที่ซ้ำกัน 3. ใช้ ifelse เพื่อเลือกและกรอกข้อมูลที่ไม่ซ้ำ

ฉันรู้วิธีการทำตามขั้นตอนที่ 1 และ 3 แต่ติดอยู่ในขั้นตอนที่ 2 ฉันคิดว่าสิ่งที่ฉันต้องทำไม่เพียง แต่ระบุ TRUE / FALSE ซ้ำกัน แต่อาจมีคอลัมน์ที่มีตัวระบุที่ไม่ซ้ำกันสำหรับคู่รายการแต่ละรายการเช่นนี้ เป็น 2 แถวพิเศษเนื่องจากขั้นตอนที่ 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

ฉันไม่แน่ใจว่าจะทำอย่างไร

สิ่งที่ฉันขอคือความช่วยเหลือในขั้นตอนที่ 2 หรืออาจจะมีวิธีที่ดีกว่าในการแก้ปัญหามากกว่าขั้นตอนที่ฉันระบุไว้

คำตอบ:


6

dplyrทางเลือกหนึ่งอาจเป็น:

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

และถ้าคุณต้องการคู่ในแต่ละคอลัมน์ด้วยการเพิ่มtidyrคุณสามารถทำได้:

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

ขอบคุณ! มันใช้งานได้ดี ฉันขอขอบคุณที่เพิ่มตัวเลือกในการแยกรายการ
Heather Clark

3

ใช้!duplicated()หลังจากsortไอเอ็นจี

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"

ขอบคุณสำหรับการตอบสนองที่รวดเร็ว อย่างไรก็ตามวิธีนี้จะลบข้อมูลที่ฉันต้องการเก็บไว้ ฉันต้องการรวมข้อมูลจากคอลัมน์ค่า 3 ที่พบใน 2 แถวของคู่รายการเดียวกัน แจ้งให้เราทราบหากนี่ยังไม่ชัดเจน
Heather Clark

2

ใช้melt/dcastจาก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

ข้อมูล

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

2

data.tableตัวเลือกอื่น:

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]

เอาท์พุท:

   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

นี่คือความพยายามของฉันโดยใช้ data.table mydfข้อมูลของคุณจะเรียกว่า ก่อนอื่นฉันเรียงfitและsitสำหรับแต่ละแถวและสร้างตัวแปรใหม่, group. จากนั้นสำหรับแต่ละกลุ่มฉันเรียงลำดับค่าในคอลัมน์ค่าสามค่า (เช่น value1, value2 และ value3) ในที่สุดฉันก็แยกแถวแรกสำหรับแต่ละกลุ่ม

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

ข้อมูล

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

นอกจากนี้ยังสามารถทำได้โดยใช้tidyr's pivot_longerด้วยvalues_drop_na = TRUEรวมกับ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

ข้อมูล

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