mutate_if - предупреждающее сообщение - PullRequest
2 голосов
/ 16 февраля 2020

Привет всем,

library(dplyr)
library(tibble)
mtcars %>%
  rownames_to_column("modelle") %>%
  mutate_if(~is.numeric(.x) & mean(.x) > 50, ~(.x / 1000))

Warning message:
In mean.default(.x) : argument is not numeric or logical: returning NA

Эта ошибка, кажется, из-за символьного вектора. Это работает, но все еще очень уродливо. Я сделал что-то не так, и что можно сделать лучше в этом случае?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 16 февраля 2020

R не векторизует короткое замыкание &, поэтому оно работает и is.numeric и mean во всех столбцах. Поскольку ваш первый столбец (modelle), очевидно, character, он терпит неудачу.

Однако на самом деле его не нужно векторизовать. Если вы перейдете от векторизованного & к двоичному &&, R закоротит его, и вы получите желаемое поведение.

mtcars %>%
  rownames_to_column("modelle") %>%
  mutate_if(~is.numeric(.x) && mean(.x) > 50, ~(.x / 1000)) %>%
  head()
#             modelle  mpg cyl  disp    hp drat    wt  qsec vs am gear carb
# 1         Mazda RX4 21.0   6 0.160 0.110 3.90 2.620 16.46  0  1    4    4
# 2     Mazda RX4 Wag 21.0   6 0.160 0.110 3.90 2.875 17.02  0  1    4    4
# 3        Datsun 710 22.8   4 0.108 0.093 3.85 2.320 18.61  1  1    4    1
# 4    Hornet 4 Drive 21.4   6 0.258 0.110 3.08 3.215 19.44  1  0    3    1
# 5 Hornet Sportabout 18.7   8 0.360 0.175 3.15 3.440 17.02  0  0    3    2
# 6           Valiant 18.1   6 0.225 0.105 2.76 3.460 20.22  1  0    3    1

Дальнейшая демонстрация того, что & не является коротким замыканием.

mymean <- function(x, ...) {
  if (is.character(x)) {
    message("character?")
    return(Inf) # this is certainly not the right thing to do in general ...
  } else mean(x, ...)
}
mtcars %>%
  rownames_to_column("modelle") %>%
  mutate_if(~is.numeric(.x) & mymean(.x) > 50, ~(.x / 1000)) %>%
  head()
# character?
#             modelle  mpg cyl  disp    hp drat    wt  qsec vs am gear carb
# 1         Mazda RX4 21.0   6 0.160 0.110 3.90 2.620 16.46  0  1    4    4
# 2     Mazda RX4 Wag 21.0   6 0.160 0.110 3.90 2.875 17.02  0  1    4    4
# 3        Datsun 710 22.8   4 0.108 0.093 3.85 2.320 18.61  1  1    4    1
# 4    Hornet 4 Drive 21.4   6 0.258 0.110 3.08 3.215 19.44  1  0    3    1
# 5 Hornet Sportabout 18.7   8 0.360 0.175 3.15 3.440 17.02  0  0    3    2
# 6           Valiant 18.1   6 0.225 0.105 2.76 3.460 20.22  1  0    3    1

Если бы произошло короткое замыкание , то mymean никогда бы не добралось до сообщения. (Я не думаю, что это mymean является жизнеспособной заменой здесь по нескольким причинам: (1) использование Inf было исключительно для обеспечения условия вне вызова mean сработало, но если возникает ошибка / предупреждение и ожидается numeric, то обычно следует возвращать NA или NaN, а не число ... даже если вы не считаете Inf реальным используемым числом . (2) Он обращается к симптому , а не к проблеме . Проблема заключается в отсутствии короткого замыкания в векторизованных логических выражениях.)

1 голос
/ 16 февраля 2020

Вы должны использовать «&&» вместо «&». Первый используется для скаляров, а второй - для векторов. В вашем случае среднее скалярное значение.

library(dplyr)
library(tibble)
mtcars %>%
rownames_to_column("modelle") %>%
mutate_if(~is.numeric(.x) && mean(.x) > 50, ~(.x / 1000))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...