dplyr slice ifelse grepl фильтр в r: неожиданный результат

#r

#r

Вопрос:

Фрейм данных: Всем привет, я надеюсь, что у вас все в порядке. Я пытаюсь получить вывод из приведенного ниже фрейма данных следующим образом: если для клиента есть шаблон для комментария «Проверено», тогда сохраните все остальные строки, если комментарии не проверены, затем снова сохраните все остальные строки, только проверенные Первое решение, указанное ниже, сохраняет только одну строку на клиента (неправильную) секундурешение сохраняет все строки (неправильные). Хотя мне кажется, что логика правильная, где-то я делаю что-то не так, и я не получаю, пожалуйста, будьте так добры, чтобы дать подсказку Заранее большое вам спасибо за вашу любезную поддержку*

         ID = c("H1", "H1"," H1"," H2", "H2", "H3", "H3"," H3", "H4")
        rating = c("C", "C", "C ","D", "C", "C",  "C ", "C ", "C")
        Commnets= c("Audited", "Audited Co", "Unaudited",
                    "Audited","Audited", 
                    "Unaudited Co",  "Unaudited", "Unaudited", "Audited")
        Date= c("2018-12-10", "2018-12-10", "2018-11-10",
                "2018-11-10","2018-11-10", 
                "2018-10-10",  "2018-10-02", "2018-10-02", "2020-09-03")
    
    df<-data.frame(ID,rating,Commnets,Date,stringsAsFactors=FALSE)
    
    #Solution
    
    
    #1.
    
    df<-df%>%
        mutate(ID = trimws(ID))%>%
        group_by(ID) %>%
        arrange(ID,Commnets,desc(Date)) %>% # in each group, arrange in desc by time stamp
        slice(ifelse(sum(grepl("Audited",Commnets),na.rm = TRUE) == n(), 1:n(), 
                     ifelse(sum(grepl("Unaudited",Commnets),na.rm = TRUE) == n(),1:n(),1:sum(grepl("Audited",Commnets),na.rm = TRUE))))
    
    #2.
    df<-df%>%
        mutate(ID = trimws(ID))%>%
        arrange(ID,Commnets,desc(Date)) %>%
        group_by(ID) %>% # in each group, arrange in desc by time stamp
        filter(ifelse(sum(grepl("Audited",Commnets),na.rm = TRUE) == n(),grepl("Audited",Commnets),ifelse(sum(grepl("Unaudited",Commnets),na.rm = TRUE)==n(),grepl("Unaudited",Commnets),grepl("Audited",Commnets)))
 

Ответ №1:

После группировки по «ID» те, filter у которых есть all элементы в «Commnets», имеют подстроку «Проверенный» или | all «Неаудированный» или else возвращают первый «Проверенный»

 library(dplyr)
 df %>% 
    mutate(Date = as.Date(Date)) %>%
    arrange(ID,Commnets,desc(Date)) %>%
    group_by(ID = trimws(ID)) %>%
    mutate(flag = all(grepl('\bAudited', 
          Commnets))|all(grepl('\bUnaudited', Commnets))) %>%
    filter(flag| (!flag amp;  grepl('\bAudited', Commnets))) %>% 
    filter(if(all(!flag)) row_number() == 1 else TRUE) %>% 
    ungroup %>%
    select(-flag)
# A tibble: 7 x 4
#  ID    rating Commnets     Date      
#  <chr> <chr>  <chr>        <date>    
#1 H2    D      Audited      2018-11-10
#2 H3    C      Unaudited    2018-10-02
#3 H1    C      Audited      2018-12-10
#4 H2    C      Audited      2018-11-10
#5 H3    C      Unaudited    2018-10-02
#6 H3    C      Unaudited Co 2018-10-10
#7 H4    C      Audited      2020-09-03
 

Или, если мы хотим сохранить все «проверенные», просто удалите второй filter

 df %>%  
 mutate(Date = as.Date(Date)) %>%
 arrange(ID,Commnets,desc(Date)) %>%
 group_by(ID = trimws(ID)) %>%
 mutate(flag = all(grepl('\bAudited', Commnets))|all(grepl('\bUnaudited', Commnets))) %>%
 filter(flag| (!flag amp;  grepl('\bAudited', Commnets))) %>%
 ungroup %>% 
 select(-flag)
# A tibble: 8 x 4
#  ID    rating Commnets     Date      
#  <chr> <chr>  <chr>        <date>    
#1 H2    D      Audited      2018-11-10
#2 H3    C      Unaudited    2018-10-02
#3 H1    C      Audited      2018-12-10
#4 H1    C      Audited Co   2018-12-10
#5 H2    C      Audited      2018-11-10
#6 H3    C      Unaudited    2018-10-02
#7 H3    C      Unaudited Co 2018-10-10
#8 H4    C      Audited      2020-09-03
 

Комментарии:

1. Привет @akrun, большое спасибо за ваш отзыв. Только один вопрос с моей стороны: в столбце флага будут либо все проверенные (true), либо все неаудированные (true) или False. Case1 все проверено (затем возвращает all (flag) как(! flag amp;) всегда false). Случай 2 все неотредактированные (затем возвращает все как (аналогично случаю 1). Смешанный случай 3: флаг false -> filter (вернет пересечение TRUE и TRUE). Это правильно? спасибо 🙂

2. @erv Я понимаю вопрос о возврате строк, если все коммнеты являются «Проверенной» подстрокой или все «неаудированные». и если это не так (в моем первом решении), оно возвращает первую «Проверенную» строку, 2) решение, оно возвращает все «Проверенные» строки. Если такова логика, то его тоже можно сделать более компактным

3. Привет @akrun, ваше решение отлично решило мою проблему, мои комментарии были больше направлены на понимание самого кода, но я думаю, что и это я понял, я хотел бы вас очень поблагодарить и пожелать вам очень приятных выходных.