Группировка data.frame и фильтрация на основе нескольких условий - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть data.frame с несколькими столбцами:

df <- data.frame(sgid = c("sg1","sg1","sg2","sg3"), stid = c(NA,"st1",NA,NA), spid = c(NA,NA,NA,"sp3"), sch = c("sch1","sch1","sch2","sch2"), sst = c(11,11,32,21), snd = c(21,21,46,34),
                 qgid = c("qg1","qg1","qg1","qg1"), qtid = c("qt1","qt1","qt1","qt1"), qpid = c("qp1","qp1","qp1","qp1"), qch = c("qch1","qch1","qch1","qch1"), qst = c(111,111,234,21), qnd = c(211,211,267,34))

Это data.frame описывает отображение одной последовательности (т.е. запрос) в базу данных других последовательностей (например, поиск).

Последовательности поиска и запроса идентифицируются тремя наборами идентификаторов: gid, tid и pid (с префиксами s и q для поиска и запроса соответственно) и координатами совпадений.описываются строкой: ch и двумя целыми числами: st и nd (снова с префиксами s и q для поиска и запроса соответственно).

tid и pidподмножества gid в случае поиска, следовательно, в базе данных поиска они хранятся в виде отдельных строк.Таким образом, возможно, что запрос «ударит» как gid, так и tid и / или pid в разных координатах.

Однако, как и в случае строк 1 и 2 в df, запрос переходит к поиску внутри tid, и, следовательно, координаты поиска и запроса строк 1 и 2 идентичны.

Итак, я ищу это function (вероятно, через dplyr::group и dplyr::filter), которые будут возвращать уникальный df на основе приведенного выше определения.

Это мой грубый способ достижения этого:

tmp.df <- df %>% dplyr::select(-stid,-spid) %>% unique()

uniq.df <- do.call(rbind,lapply(1:nrow(tmp.df),function(i){
  tmp.df.i <- tmp.df[i,,drop=F] %>% dplyr::left_join(df)
  if(!(all(is.na(tmp.df.i$stid) & is.na(tmp.df.i$spid)))){
    tmp.df.i <- tmp.df.i[which(!is.na(tmp.df.i$stid) | !is.na(tmp.df.i$spid)),,drop=F]
  } else{
    tmp.df.i <- tmp.df.i %>%
      dplyr::select(-stid,-spid) %>%
      dplyr::mutate(stid=NA,spid=NA)
  }
  return(tmp.df.i)
}))

#organize the columns of uniq.df to the order of df:
uniq.df <- uniq.df %>% dplyr::select_(.dots = colnames(df))

> uniq.df
   sgid stid spid  sch sst snd qgid qtid qpid  qch qst qnd
2   sg1  st1 <NA> sch1  11  21  qg1  qt1  qp1 qch1 111 211
1   sg2 <NA> <NA> sch2  32  46  qg1  qt1  qp1 qch1 234 267
11  sg3 <NA>  sp3 sch2  21  34  qg1  qt1  qp1 qch1  21  34

В поисках чего-то более элегантного.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Как примерно так с dplyr:

cols <- setdiff(names(df), c("stid", "spid"))

df %>% group_by_at(cols) %>% 
  summarise(stid = ifelse(length(unique(stid)) == 1,
                          unique(stid), 
                          unique(stid)[! is.na(unique(stid))]),
            spid = ifelse(length(unique(spid)) == 1,
                          unique(spid), 
                          unique(spid)[! is.na(unique(spid))]))

Или вы можете использовать функцию Coalesce из пакета DescTools (или даже определить свою собственную функцию для выбора первой не NA)значение):

df %>% group_by_at(cols) %>% 
  summarise(stid = DescTools::Coalesce(stid),
            spid = DescTools::Coalesce(spid))
0 голосов
/ 04 февраля 2019

data.table решение

пример данных

#    sgid stid spid  sch sst snd qgid qtid qpid  qch qst qnd
# 1:  sg1 <NA> <NA> sch1  11  21  qg1  qt1  qp1 qch1 111 211
# 2:  sg1  st1 <NA> sch1  11  21  qg1  qt1  qp1 qch1 111 211
# 3:  sg2 <NA> <NA> sch2  32  46  qg1  qt1  qp1 qch1 234 267
# 4:  sg3 <NA>  sp3 sch2  21  34  qg1  qt1  qp1 qch1  21  34

код

library( data.table )
setDT( df )
#get columns you wish to exclude from duplication-check
cols <- c( "stid", "spid" )
#keep non-duplicated rows, based on a subset of df (without the columns in `cols`)
df[ !duplicated( df[, !..cols] ), ][]

#    sgid stid spid  sch sst snd qgid qtid qpid  qch qst qnd
# 1:  sg1 <NA> <NA> sch1  11  21  qg1  qt1  qp1 qch1 111 211
# 2:  sg2 <NA> <NA> sch2  32  46  qg1  qt1  qp1 qch1 234 267
# 3:  sg3 <NA>  sp3 sch2  21  34  qg1  qt1  qp1 qch1  21  34

альтернатива
, если вы не хотите сохранять первый ряд дубликата, но последний, используйте:

df[ !duplicated( df[, !..cols], fromLast = TRUE ), ][]  #<-- note fromlast-argument!

#    sgid stid spid  sch sst snd qgid qtid qpid  qch qst qnd
# 1:  sg1  st1 <NA> sch1  11  21  qg1  qt1  qp1 qch1 111 211
# 2:  sg2 <NA> <NA> sch2  32  46  qg1  qt1  qp1 qch1 234 267
# 3:  sg3 <NA>  sp3 sch2  21  34  qg1  qt1  qp1 qch1  21  34
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...