Почему case_when () вычисляет ложное условие?

1

У меня есть data.frame с групповой переменной и целочисленной переменной с отсутствующими данными.

df<-data.frame(group=c(1,1,2,2,3,3),a=as.integer(c(1,2,NA,NA,1,NA)))

Я хочу вычислить максимально доступное значение переменнойa внутри каждой группы: в моем примере я должен получить 2 для группы 1,NA для группы 2 и 1 для группы 3.

df %>% group_by(group) %>% mutate(max.a=case_when(sum(!is.na(a))==0 ~ NA_integer_,
                                                  T ~ max(a,na.rm=T)))

Приведенный выше код генерирует ошибку, по-видимому, потому что в группе 2 все значенияa отсутствуют такmax(a,na.rm=T) установлен на-Inf , которое не является целым числом.

Почему этот случай вычислен для группы 2, тогда как условие ложно, как подтверждает следующая проверка?

df %>% group_by(group) %>% mutate(test=sum(!is.na(a))==0)

Я нашел обходной путь преобразованияa чтобы удвоиться, но я все равно получаю предупреждение и недовольство тем, что не нашел лучшего решения.

  • 2
    case_when векторизован. Вы используете его на скаляре, полученном в результате sum поэтому не работает должным образом. Используйте невекторизованный, if как предлагается в ответе
Теги:
dplyr
CodeFix

3 ответа

2
Лучший ответ

case_whenоценивает всю правую часть условия независимо от того, выполняется условие или нет, поэтому вы получаете ошибку. Вы можете использоватьhablar::max_ который возвращаетсяNA если все значенияNA .

library(dplyr)

df %>% 
  group_by(group) %>% 
  mutate(max.a= hablar::max_(a)) %>%
  ungroup

#  group     a max.a
#  <dbl> <int> <int>
#1     1     1     2
#2     1     2     2
#3     2    NA    NA
#4     2    NA    NA
#5     3     1     1
#6     3    NA     1
Поделиться
Источник
1

Этот код выдает предупреждение, но он работает.

library(dplyr)
df %>% 
  group_by(group) %>% 
  dplyr::summarise(max.a = max(a, na.rm=TRUE))

Выход:

  group max.a
  <dbl> <dbl>
1     1     2
2     2  -Inf
3     3     1
Поделиться
Источник
1

Вместо использованияcase_when Я бы предложил использоватьif () заявление вроде так:

library(dplyr)

df <- data.frame(group = c(1, 1, 2, 2, 3, 3), a = as.integer(c(1, 2, NA, NA, 1, NA)))

df %>%
  group_by(group) %>%
  mutate(max.a = if (all(is.na(a))) NA_real_ else max(a, na.rm = T))
#> # A tibble: 6 x 3
#> # Groups:   group [3]
#>   group     a max.a
#>   <dbl> <int> <dbl>
#> 1     1     1     2
#> 2     1     2     2
#> 3     2    NA    NA
#> 4     2    NA    NA
#> 5     3     1     1
#> 6     3    NA     1
Поделиться
Источник

Другие вопросы

CodeFix
Цитата дня

"Завидую тестировщикам: все хотят с ними дружить."

Эндрю Таненбаум