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
NULL
in 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 thatacross
uses.Using
any(.)
inside theif_else
collapses the length of the first argumentcondition=
will always be seen as length-1; instead, we need torep
eat 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)))