Интерпретация предупреждения "условие имеет длину> 1" из функции if

У меня есть массив:

a <- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

и хотел бы реализовать следующую функцию:

w<-function(a){
  if (a>0){
    a/sum(a)
  }
  else 1
}

Эта функция хотела бы проверить, есть ли какое-либо значение в a больше 0, и если да, то разделите каждый элемент на сумму суммы.

В противном случае он должен просто записать 1.

Я получаю следующее предупреждение:

 Warning message:
 In if (a > 0) { :
 the condition has length > 1 and only the first element will be used

Как я могу исправить функцию?

7 ответов

Решение

Может ты хочешь ifelse:

a <- c(1,1,1,1,0,0,0,0,2,2)
ifelse(a>0,a/sum(a),1)

 [1] 0.125 0.125 0.125 0.125 1.000 1.000 1.000 1.000
 [9] 0.250 0.250

if утверждение не векторизовано. Для векторизованных операторов if следует использовать ifelse, В вашем случае достаточно написать

w <- function(a){
if (any(a>0)){
  a/sum(a)
}
  else 1
}

или короткая векторизованная версия

ifelse(a > 0, a/sum(a), 1)

Это зависит от того, что вы хотите использовать, потому что первая функция дает выходной вектор длины 1 (в другой части) и ifelse дает выходной вектор длины, равный длине a,

Просто добавив пункт ко всей дискуссии о том, почему появляется это предупреждение (мне раньше было непонятно). Причина, по которой каждый получает это, как упоминалось ранее, заключается в том, что "a" в данном случае является вектором, а неравенство "a>0" создает другой вектор TRUE и FALSE (где "a" равно> 0 или нет).

Если вы хотите вместо этого протестировать любое значение "a>0", вы можете использовать функции - "any" или "all".

Лучший

Вот простой способ без ifelse:

(a/sum(a))^(a>0)

Пример:

a <- c(0, 1, 0, 0, 1, 1, 0, 1)

(a/sum(a))^(a>0)

[1] 1.00 0.25 1.00 1.00 0.25 0.25 1.00 0.25

Использование lapply Функция после создания вашей функции в обычном режиме.

lapply(x="your input", fun="insert your function name")

lapply дает список, так что используйте unlist функция, чтобы вывести их из функции

unlist(lapply(a,w))

Я пытался разобраться в этом вопросе, когда пытался сделать что-то похожее, когда определял функцию и вызывался с массивом, как указали другие.

Вы можете сделать что-то подобное, однако для этого сценария это менее элегантно по сравнению с методом Свена.

sapply(a, function(x) afunc(x))

afunc<-function(a){
  if (a>0){
    a/sum(a)
  }
  else 1
}

Я бы сказал, что наиболее эффективным способом является ответ пользователя 1317221_G. Однако, если вы хотите вернуться к основам, то цикл по длине вашего вектора (поскольку функция if не работает с длиной вектора) с использованием функции for был бы полезен.

      w <- c() ##creates empty vector named 'w'
for(i in 1:length(a)){
  if (a[i]>0){
    w[i] <- a[i]/sum(a)
  }
  else 
    w[i] <- 1
}
Другие вопросы по тегам