Add +1 (>1) after every time a condition is met

Viewed 89

(sorry, really don't know how to better phrase this question)

I have a column "have" with 1s and 0s. I want to create a new column "want" where, each time a 1 has occurred, the value of 0 increases to 2, then 3, then 4, etc. 0 should never be 1.

Example:

data <- data.frame(have = (c('0', '0', '0', '0', '1', '0', '1', '0', '0', '1')), 
                   want = (c('0', '0', '0', '0', '1', '2', '1', '3', '3', '1')))                       
5 Answers

You could do:

data <- data.frame(have = (c('0', '0', '0', '0', '1', '0', '1', '0', '0', '1')))  

data$want <- cumsum(as.numeric(data$have)) + 1
data$want[data$want == "1"] <- "0"
data$want[data$have == "1"] <- "1"

data
#>    have want
#> 1     0    0
#> 2     0    0
#> 3     0    0
#> 4     0    0
#> 5     1    1
#> 6     0    2
#> 7     1    1
#> 8     0    3
#> 9     0    3
#> 10    1    1

Created on 2022-04-06 by the reprex package (v2.0.1)

Using the rle

f <- \(x) {
  rl <- rle(x)
  rl0 <- which(rl$values == 0)
  rl$values[rl0[-1]] <- seq_along(rl$values[rl0[-1]]) + 1
  rep(rl$values, rl$lengths)
}

transform(data, want=f(have))
#    have want
# 1     0    0
# 2     0    0
# 3     0    0
# 4     0    0
# 5     1    1
# 6     0    2
# 7     1    1
# 8     0    3
# 9     0    3
# 10    1    1

Here's another alternative:

transform(data,
          want = pmin(cumsum(have) + cummax(have), 0^-(have != 1)))

   have want
1     0    0
2     0    0
3     0    0
4     0    0
5     1    1
6     0    2
7     1    1
8     0    3
9     0    3
10    1    1
df <- data.frame(have = (c('0', '0', '0', '0', '1', '0', '1', '0', '0', '1')), 
                   want = (c('0', '0', '0', '0', '1', '2', '1', '3', '3', '1')))


df$want2 <- ifelse(df$have == 1, 1, ifelse(cumsum(df$have) == 0, 0, 1 + cumsum(df$have == 1)))

df

What about this?

transform(
    df,
    want = replace(
        replace(
            cumsum(have == 1) + 1,
            have == 1,
            1
        ),
        seq_along(have) < min(which(have == 1)),
        0
    )
)

Output

   have want
1     0    0
2     0    0
3     0    0
4     0    0
5     1    1
6     0    2
7     1    1
8     0    3
9     0    3
10    1    1
Related