Tidyverse: последовательное появление нулей - PullRequest
2 голосов
/ 17 марта 2020

Хотите создать столбец b из a так, чтобы

if a == 1 then b = 0 
else b = counting start from 1
then if  a == 1 then b = 0 
else b = counting start from 1

, как указано в tb1 ниже.

Мой рабочий пример приведен ниже:

library(tidyverse)
tb1 <- 
  tibble(
    a = c(1, rep(0, 4), 1, rep(0, 5), 1, 1, rep(0, 4), 1, rep(0, 2))
  , b = c(0, 1:4, 0, 1:5, 0, 0, 1:4, 0, 1:2)
  )
tb1
#> # A tibble: 20 x 2
#>        a     b
#>    <dbl> <dbl>
#>  1     1     0
#>  2     0     1
#>  3     0     2
#>  4     0     3
#>  5     0     4
#>  6     1     0
#>  7     0     1
#>  8     0     2
#>  9     0     3
#> 10     0     4
#> 11     0     5
#> 12     1     0
#> 13     1     0
#> 14     0     1
#> 15     0     2
#> 16     0     3
#> 17     0     4
#> 18     1     0
#> 19     0     1
#> 20     0     2

tb2 <-
  tb1 %>% 
  mutate(b1 = if_else(condition = a == 1, true = 0, false = 1)) %>% 
  group_by(a) %>% 
  mutate(b2 = cumsum(b1))

tb2
#> # A tibble: 20 x 4
#> # Groups:   a [2]
#>        a     b    b1    b2
#>    <dbl> <dbl> <dbl> <dbl>
#>  1     1     0     0     0
#>  2     0     1     1     1
#>  3     0     2     1     2
#>  4     0     3     1     3
#>  5     0     4     1     4
#>  6     1     0     0     0
#>  7     0     1     1     5
#>  8     0     2     1     6
#>  9     0     3     1     7
#> 10     0     4     1     8
#> 11     0     5     1     9
#> 12     1     0     0     0
#> 13     1     0     0     0
#> 14     0     1     1    10
#> 15     0     2     1    11
#> 16     0     3     1    12
#> 17     0     4     1    13
#> 18     1     0     0     0
#> 19     0     1     1    14
#> 20     0     2     1    15

Ответы [ 2 ]

1 голос
/ 17 марта 2020

Сначала сгруппируйте по каждому чанку, который начинается с a=1, что можно сделать с помощью cumsum(a). Затем в каждой такой группе выполните подсчет значений a, равных 0, следующим образом:

tb1 %>% 
  group_by(grouper = cumsum(a)) %>% 
  mutate(b = cumsum(a == 0)) %>% 
  ungroup() %>% 
  select(-grouper)

       a     b
   <dbl> <int>
 1     1     0
 2     0     1
 3     0     2
 4     0     3
 5     0     4
 6     1     0
 7     0     1
 8     0     2
 9     0     3
10     0     4
11     0     5
12     1     0
13     1     0
14     0     1
15     0     2
16     0     3
17     0     4
18     1     0
19     0     1
20     0     2
1 голос
/ 17 марта 2020

Один из вариантов может быть:

tb1 %>%
 group_by(rleid = with(rle(a), rep(seq_along(lengths), lengths))) %>%
 mutate(b = 1:n() * (a != 1)) 

       a     b rleid
   <dbl> <int> <int>
 1     1     0     1
 2     0     1     2
 3     0     2     2
 4     0     3     2
 5     0     4     2
 6     1     0     3
 7     0     1     4
 8     0     2     4
 9     0     3     4
10     0     4     4
11     0     5     4
12     1     0     5
13     1     0     5
14     0     1     6
15     0     2     6
16     0     3     6
17     0     4     6
18     1     0     7
19     0     1     8
20     0     2     8
...