Мы можем group_by
ID
и использовать mutate_all
с replace
library(dplyr)
df %>%
group_by(ID) %>%
mutate_all(~replace(., all(. == 0), NA))
# ID A1 B1
# <fct> <dbl> <dbl>
#1 A NA 1
#2 A NA 0
#3 A NA 1
#4 A NA 0
#5 B 1 NA
#6 B 0 NA
#7 B 1 NA
Если есть другие столбцы, и мы хотим применить это только к определенным столбцам, мы можем использовать mutate_at
df %>%
group_by(ID) %>%
mutate_at(vars(A1,B1), ~replace(., all(. == 0), NA))
Используя case_when
, мы можем сделать это как
df %>%
group_by(ID) %>%
mutate_all(~case_when(all(. == 0) ~ NA_real_, TRUE ~ .))
Проблема в попытке OP заключалась в том, что в case_when
не определено ни одного случая TRUE
, поэтому, если не найдено ни одного условия, по умолчанию возвращается NA
. От ?case_when
Если не найдено ни одного случая, возвращается NA.
Так что, если мы определим случай TRUE
, он будет работать как положено. Также мы не должны проверять sum(A1)==0
, потому что, если в столбце есть отрицательные и положительные значения (например, -2, +2), они будут складываться как 0, что даст неожиданные результаты.
df%>%
group_by(ID) %>%
mutate(A1 = case_when(all(A1 == 0) ~ NA_real_, TRUE ~ A1),
B1 = case_when(all(B1 == 0) ~ NA_real_, TRUE ~ B1))