This is a follow up question to this post
I want to replace values in t1, t2, and t3 according to whether or not column v3 contains a 1, a 2, or a 3 by group in v2.
My goal is to write Nav in column t1 if for a given group of v2 column v3 has value 1.
The problem I face comes from the else part of the statement. I would like that if in the example above v3 does not contain 1 that column t1 stays the same.
Any idea?
mutate(across(starts_with("t"), ~if_else(any(v3==i),"NAv", HERE COLUMN REMAINS UNCHANGED)))
df <- data.frame (v1 = c("Fran", "Fran", "Fran", "Belg", "Belg", "Belg"),
v2 = c(1201, 1201, 1202, 1203, 1204, 1205),
v3 = c(1, 2, 1, 1, 3, 1),
t1 = c(NA,NA,NA,NA,NA,NA),
t2 = c(NA,NA,NA,NA,NA,NA),
t3 = c(NA,NA,NA,NA,NA,NA)
)
for (i in 1:3) {
df <- df %>%
group_by(v2) %>%
mutate(across(starts_with("t"), ~if_else(any(v3==i),"NAv", NULL)))
}
CodePudding user response:
Three problems:
Your
t*columns in this sample data are of classlogical, notcharacter, so I'll coerce them in the firstmutate. (This step may not be necessary with your real data.)You cannot use
NULLin any portion of anifelse/if_else. Since you want to retain the previous value if the condition is not met, then we'll use the.placeholder thatacrossuses.Using
any(.)inside theif_elsecollapses the length of the first argumentcondition=will always be seen as length-1; instead, we need torepeat the return fromany(.)for as many rows as we have, usingrep(.., n()).
df %>%
mutate(across(starts_with("t"), as.character)) %>%
group_by(v2) %>%
mutate(across(starts_with("t"), ~ if_else(rep(any(v3 == 1), n()), "NAv", .) )) %>%
ungroup()
# # A tibble: 6 x 6
# v1 v2 v3 t1 t2 t3
# <chr> <dbl> <dbl> <chr> <chr> <chr>
# 1 Fran 1201 1 NAv NAv NAv
# 2 Fran 1201 2 NAv NAv NAv
# 3 Fran 1202 1 NAv NAv NAv
# 4 Belg 1203 1 NAv NAv NAv
# 5 Belg 1204 3 NA NA NA
# 6 Belg 1205 1 NAv NAv NAv
CodePudding user response:
in across(), .x stands in for the current column. So:
mutate(across(starts_with("t"), ~ifelse(any(v3==i),"NAv", .x)))
