I'm trying to calculate the minimum across rows while compensating for rows where all values of interest are NA:
library(dplyr)
testDf <- tibble(a = 1:4,
b = c(NA, 5:7),
c = c(NA, 8, NA, 10),
d = c(NA, 11:13)
) %>%
rowwise() %>%
mutate(e = case_when(all(is.na(c_across(b:d))) ~ NA_integer_,
.default = min(c_across(b:d), na.rm=TRUE))
) %>%
ungroup()
I get the following warning for row 1:
Caused by warning in
min()
: ! no non-missing arguments to min; returning Inf
However, the output indicates that the code works as intended:
testDf
# A tibble: 4 × 5
a b c d e
<int> <int> <dbl> <int> <dbl>
1 1 NA NA NA NA
2 2 5 8 11 5
3 3 6 NA 12 6
4 4 7 10 13 7
Column e has NA
in the first row, 6 in the third, and no Inf
values. I've tried replacing .default =
with TRUE ~
and !all(is.na(c_across(b:d))) ~
, as well as replacing NA_integer_
with NA_real_
and still get the same warning.
My understanding is that .default
in case_when
only applies when the left side of the previous equation returns FALSE or NA. Testing with the following does indeed yield TRUE for the first row of f and FALSE for the rest, so it seems like the operation on the right side of the .default
line should skip the first row:
testDf %>%
rowwise() %>%
mutate(f = all(is.na(c_across(b:d))))
# A tibble: 4 × 6
# Rowwise:
a b c d e f
<int> <int> <dbl> <int> <dbl> <lgl>
1 1 NA NA NA NA TRUE
2 2 5 8 11 5 FALSE
3 3 6 NA 12 6 FALSE
4 4 7 10 13 7 FALSE
I'm not a fan of suppressing warnings in general, and when there doesn't appear to be a problem in particular. Can't seem to pin down where I've gone wrong or if it's just a bug.
I believe the warning message is correct. case_when
evaluates all its possible values before "deciding" which one to return. You're applying min
to columns c
and d
in a rowwise
manner. Some rows have NA
in these columns. Therefore, case_when
attempts to evaluate min(NA, na.rm = TRUE)
for these rows and reports the warning for these intermediate values. But then case_when
applies its logic to determine the final result.
I agree it's better to avoid errors and warnings rather than suppressing them. To avoid the warning, you can switch to ifelse
, which evaluates its arguments lazily:
testDf <- tibble(
a = 1:4,
b = c(NA, 5:7),
c = c(NA, 8, NA, 10),
d = c(NA, 11:13)
) %>%
rowwise() %>%
mutate(
e = ifelse(
all(is.na(c_across(b:d))),
NA_integer_,
min(c_across(b:d), na.rm=TRUE)
)
) %>%
ungroup()