I have binary data as below:
ID <- c("A", "B", "C", "D", "E", "F")
Q0 <- c(0, 0, 0, 0, 0, 0)
Q1 <- c(0, 1, 0, 0, NA, 1)
Q2 <- c(0, NA, 1, 0, NA, 1)
Q3 <- c(0, NA, NA, 1, NA, 1)
Q4 <- c(0, NA, NA, 1, NA, 1)
dta <- data.frame(ID, Q0, Q1, Q2, Q3, Q4)
If there is 1 for a row in one of the columns, all the subsequent columns should be 1 as well. If there is 0 or NA, the next column should stay as is.
Stated differently, how can I change the value of multiple columns based conditionally on the value of a column in a relative position?
The intended output for the above data frame is:
ID Q0 Q1 Q2 Q3 Q4
A 0 0 0 0 0
B 0 1 1 1 1
C 0 0 1 1 1
D 0 0 0 1 1
E 0 NA NA NA NA
F 0 1 1 1 1
How can I do this? Perhaps using apply or a for loop?
Yet another dplyr + purrr option could be:
dta %>%
mutate(pmap_dfr(across(-ID), ~ `[<-`(c(...), seq_along(c(...)) > match(1, c(...)), 1)))
ID Q0 Q1 Q2 Q3 Q4
1 A 0 0 0 0 0
2 B 0 1 1 1 1
3 C 0 0 1 1 1
4 D 0 0 0 1 1
5 E 0 NA NA NA NA
6 F 0 1 1 1 1
Keeping things simple with a loop:
for (i in 3:ncol(dta)) dta[[i]][dta[[i-1]] == 1] <- 1
# ID Q0 Q1 Q2 Q3 Q4
# 1 A 0 0 0 0 0
# 2 B 0 1 1 1 1
# 3 C 0 0 1 1 1
# 4 D 0 0 0 1 1
# 5 E 0 NA NA NA NA
# 6 F 0 1 1 1 1
With dplyr + data.table inspired by Yuriy:
library(dplyr)
library(data.table)
setDT(dta)
dta[, (names(dta)[-1]) := as.list(cumany(.SD == 1)), by = ID]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With