'How can I do cumulative operations across columns (not rows)?

I have a table of customer state (0, 1 or NA) at times t1 ... t7:

##   Customer t1 t2 t3 t4 t5 t6 t7
## 1        A  0  1  1  1  0  0  0
## 2        B  0  1  1  1  0  0 NA
## 3        C  0  1  1  1  0 NA NA
## ...

How can I modify the values across columns and row-wise (per customer), so that the leftmost 1 in a row is followed by 1s only?

## desired result:
##
##   Customer t1 t2 t3 t4 t5 t6 t7
## 1        A  0  1  1  1  1  1  1
## 2        B  0  1  1  1  1  1 NA
## 3        C  0  1  1  1  1 NA NA
## ...

Example data:

## example input df_in
df_in <- structure(list(Customer = c("A", "B", "C", "D", "E", "F", "G"
), t1 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L), t2 = c(1L, 1L, 1L, 1L, 
0L, 0L, NA), t3 = c(1L, 1L, 1L, 1L, 0L, NA, NA), t4 = c(1L, 1L, 
1L, 1L, NA, NA, NA), t5 = c(0L, 0L, 0L, NA, NA, NA, NA), t6 = c(0L, 
0L, NA, NA, NA, NA, NA), t7 = c(0L, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
7L))

## desired output df_out:
df_out <- structure(list(Customer = c("A", "B", "C", "D", "E", "F", "G"
), t1 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L), t2 = c(1L, 1L, 1L, 1L, 
0L, 0L, NA), t3 = c(1L, 1L, 1L, 1L, 0L, NA, NA), t4 = c(1L, 1L, 
1L, 1L, NA, NA, NA), t5 = c(1L, 1L, 1L, NA, NA, NA, NA), t6 = c(1L, 
1L, NA, NA, NA, NA, NA), t7 = c(1L, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
7L))
r


Solution 1:[1]

One possible way ...

library(tidyverse)

df_in <-
  structure(
    list(
      Customer = c("A", "B", "C", "D", "E", "F", "G"),
      t1 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L),
      t2 = c(1L, 1L, 1L, 1L, 0L, 0L, NA),
      t3 = c(1L, 1L, 1L, 1L, 0L, NA, NA),
      t4 = c(1L, 1L, 1L, 1L, NA, NA, NA),
      t5 = c(0L, 0L, 0L, NA, NA, NA, NA),
      t6 = c(0L, 0L, NA, NA, NA, NA, NA),
      t7 = c(0L, NA, NA, NA, NA, NA, NA)
    ),
    class = "data.frame",
    row.names = c(NA, 7L)
  )

df_in |> 
  pivot_longer(starts_with("t")) |> 
  group_by(Customer) |> 
  mutate(new_value = if_else(cumsum(value) >= 1L, 1L, value)) |> 
  select(-value) |> 
  pivot_wider(names_from = name, values_from = new_value)
#> # A tibble: 7 × 8
#> # Groups:   Customer [7]
#>   Customer    t1    t2    t3    t4    t5    t6    t7
#>   <chr>    <int> <int> <int> <int> <int> <int> <int>
#> 1 A            0     1     1     1     1     1     1
#> 2 B            0     1     1     1     1     1    NA
#> 3 C            0     1     1     1     1    NA    NA
#> 4 D            0     1     1     1    NA    NA    NA
#> 5 E            0     0     0    NA    NA    NA    NA
#> 6 F            0     0    NA    NA    NA    NA    NA
#> 7 G            0    NA    NA    NA    NA    NA    NA

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Carl