Найти уникальность в строках с NA?

У меня есть фрейм данных, как показано ниже. Я хотел бы найти уникальные строки (Unique rows).

Но в этих данных у меня есть’ NA ‘ как недостающие данные. Таким образом, NA может получить любое значение, как и другие строки. Пример: в строке c6 можно NA получить 0,1 или 2 в столбце a2, или в строке c8 можно NA получить 0 или 1 в столбце a3.

С другой стороны ,в строках 1, 2 и 6 все значения, кроме NA, одинаковы, поэтому, поскольку NA может быть значением ‘0 или 1’, я хотел бы удалить эту строку и просто сохранить строку 2.

Кроме того, в строке c6 столбцы a1 и a3(исключая столбцы NA) такие же, как строки c2 и c5, и в c6 возможно NAs получить такое же значение, как c2 и c5, поэтому эта строка не является уникальной.

данные:

      a1  a2   a3   a4
c1    2    1    0   NA
c2    2    1    0    0
c3    2    1    1    0
c4    2    2    0   NA
c5    2    1    0    0
c6    2    NA   0   NA
c7    1    NA   0   NA
c8    2    0   NA   NA

Я хотел бы иметь этот выход:

выход:

     a1    a2  a3   a4
c2    2    1    0    0
c3    2    1    1    0
c4    2    2    0   NA
c7    1    NA   0   NA
c8    2    0   NA   NA

Кроме того, @ Sotos решение помочь мне больше, но в последней части после удаления NA, когда сделать шаблон для строк, его решение рассмотреть тот же шаблон (23) для c8 и c6 и удалить их. Но на самом деле c8 уникален.Кроме того, C7 уникален, но игнорирует его.

c1 <- c( 2,1,0,NA)
c2<-c( 2,1,0,0)
c3<-c(2,1,1,0)
c4<-c(2, 2,0,NA)
c5<-c( 2,1,0,0)
c6<-c(2,NA,0,NA)
c7<-c(1,NA,0,NA)
c8 <-c(2,0,NA,NA)

df<-as.data.frame(rbind(c1,c2,c3,c4,c5,c6,c7,c8))

library(stringr) 

df <- unique(df)
df$new <- apply(df, 1, function(i) paste(na.omit(i), collapse = ''))
df$new2 <- rowSums(sapply(df$new, function(i) str_detect(i, df$new)))
new_df <- subset(df, df$new2 == 1)
new_df <- new_df[, !names(new_df) %in% c('new', 'new2')]
new_df

1 ответ

  1. Ну, это не решение в стиле R и, вероятно, медленное при применении к большим фреймам данных.

    uniq = F
    i = 1
    while(!uniq){
      to.remove = vector()
      for(j in setdiff(1:nrow(df), i)){ # setdiff avoid i and j beeing identical
        row.idx = intersect(which(!is.na(df[i, ])), # get all indices which not NA
                            which(!is.na(df[j, ]))  # in both columns
        )
        if(all(df[i, row.idx] == df[j, row.idx])) # match the rows, only using the
          to.remove = union(to.remove, j)         # columns identified before
      }
      if(length(to.remove) == 0){
        uniq = T
      } else {
        df = df[-to.remove,]
        i = i + 1
      }
    }