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

#r #dplyr

Вопрос:

Я хочу отфильтровать идентификатор группы только после двух последовательных значений «да», которые наблюдаются.

 DT<-data.frame(id=c(1,1,1,2,2,2,2,3,3,3,3,3,3,3),
type=c("yes","yes","no","no","yes","yes","no","no","yes","no","yes","yes","no","yes"))
 

Желаемый результат:

    id type
   1  yes
   1  yes
   1   no
   2  yes
   2  yes
   2   no
   3  yes
   3  yes
   3   no
   3  yes
 

Я попробовал это как:

 DT<-DT %>% group_by(id) %>% 
  mutate(Tlag = lag(type), ident = type == 'yes' amp; Tlag == 'yes' ) %>%
  filter(any(ident)) %>% filter(type == 'yes' | (cumsum(type == 'yes') == 1)) %>% select(-ident)
 

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

1. В ваших данных есть неправильное написание переменной type as ype .

2. Я исправил опечатку.

Ответ №1:

Использование dplyr и вид индикатора:

 DT %>% 
  group_by(id) %>% 
  mutate(indic = ifelse(lead(type) == "yes" amp; type == "yes", 1, NA)) %>%
  fill(indic, .direction = 'down') %>% 
  filter(!is.na(indic)) %>% 
  select(-indic)
 

Выход:

 # A tibble: 10 x 2
# Groups:   id [3]
      id type  
   <dbl> <chr>
 1     1 yes  
 2     1 yes  
 3     1 no   
 4     2 yes  
 5     2 yes  
 6     2 no   
 7     3 yes  
 8     3 yes  
 9     3 no   
10     3 yes  
 

Ответ №2:

У вас почти получилось, т. е. используйте lead вместо lag и немного отрегулируйте свой порог кумуляции:

 library(tidyverse)
DT %>%
  group_by(id) %>% 
  mutate(Tlead = lead(type),
         cumsum_yes = cumsum(type == "yes" amp; Tlead == "yes"),
         cumsum_yes = if_else(is.na(cumsum_yes), lag(cumsum_yes), cumsum_yes)) %>%
  filter(cumsum_yes >=1) %>%
  select(-cumsum_yes, -Tlead)
 

что дает:

 # A tibble: 10 x 2
# Groups:   id [3]
      id type 
   <dbl> <chr>
 1     1 yes  
 2     1 yes  
 3     1 no   
 4     2 yes  
 5     2 yes  
 6     2 no   
 7     3 yes  
 8     3 yes  
 9     3 no   
10     3 yes 
 

Вот результат без удаления временных столбцов, чтобы вы могли лучше видеть, что происходит:

 # A tibble: 10 x 4
# Groups:   id [3]
      id type  Tlead cumsum_yes
   <dbl> <chr> <chr>      <int>
 1     1 yes   yes            1
 2     1 yes   no             1
 3     1 no    NA             1
 4     2 yes   yes            1
 5     2 yes   no             1
 6     2 no    NA             1
 7     3 yes   yes            1
 8     3 yes   no             1
 9     3 no    yes            1
10     3 yes   NA             1
 

Ответ №3:

Если вы используете rollapply from zoo , вы можете искать любое количество 'yes' значений.

 library(dplyr)
library(zoo)

n <- 2

DT %>%
  group_by(id) %>%
  filter(row_number() >= match(TRUE, 
           rollapply(type == 'yes', n, all, align = 'left', fill = NA))) %>%
  ungroup()

#      id type 
#   <dbl> <chr>
# 1     1 yes  
# 2     1 yes  
# 3     1 no   
# 4     2 yes  
# 5     2 yes  
# 6     2 no   
# 7     3 yes  
# 8     3 yes  
# 9     3 no   
#10     3 yes