#r
#r #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
Как я могу исправить функцию?
Комментарии:
1. @user1723765 что вы ожидаете получить в результате?
2. итак, в принципе, если a a[a> 0], то следует выполнить / sum (a), а не [a>0] / sum(a)
3. результатом были бы 0s и .166667 и т.д. Для других чисел, Но в итоге у меня все равно был бы весь вектор
4. да, я только что понял. Спасибо!
5. Содержит ли ваш фактический вектор только нули и единицы?
Ответ №1:
может быть, вы хотите 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
Комментарии:
1. Предупреждение: ifelse использует столько элементов из вашего решения, сколько элементов в условии! Оно не предупреждает об этом. Например,
ifelse(TRUE, 1:5, 5:1)
возвращает1
как ответ, а не1:5
. ifelse(c(T, T), 1:5, 5:1)` возвращаетc(1, 2)
и т.д. Используйте с осторожностью.
Ответ №2:
if
оператор не векторизован. Для векторизованных операторов if вам следует использовать ifelse
. В вашем случае достаточно написать
w <- function(a){
if (any(a>0)){
a/sum(a)
}
else 1
}
или короткая векторизованная версия
ifelse(a > 0, a/sum(a), 1)
Это зависит от того, какую функцию вы хотите использовать, потому что первая функция выдает выходной вектор длиной 1 (в части else) и ifelse
выдает выходной вектор длиной, равной длине a
.
Комментарии:
1. почему, о, почему, если все остальное в R-land векторизовано … ‘if’ нет? Smdh.
2. Ваше решение с if (any()) помогло мне 9 лет спустя. Ты гений. Спасибо!
Ответ №3:
Просто добавляю точку ко всему обсуждению того, почему появляется это предупреждение (раньше мне это было непонятно). Причина, по которой это происходит, как упоминалось ранее, заключается в том, что ‘a’ в данном случае является вектором, а неравенство ‘a>0’ создает другой вектор TRUE и FALSE (где ‘a’ равно > 0 или нет).
Если вы хотите вместо этого проверить, есть ли какое-либо значение ‘a> 0’, вы можете использовать функции — ‘any’ или ‘all’
Лучшие
Ответ №4:
Вот простой способ без 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
Комментарии:
1. Это превосходит
ifelse
примерно в 7 раз (для массива из 100000 элементов).2. Не могли бы вы порекомендовать краткое объяснение / документацию этого
^
оператора (например, как он называется и как он работает). Предпочтительно что-то более простое, чем документация по арифметическим операторам …3. @thefor ecologist Для возведения в степень используется оператор
^
. Командаx ^ y
означает:x
возведена в степеньy
. Код2 ^ 3
будет вычислен2 * 2 * 2
.
Ответ №5:
Я столкнулся с этим вопросом, когда попытался сделать что-то подобное, где я определял функцию, и она вызывалась с массивом, как указывали другие
Вы могли бы сделать что-то подобное, однако для этого сценария это менее элегантно по сравнению с методом Sven.
sapply(a, function(x) afunc(x))
afunc<-function(a){
if (a>0){
a/sum(a)
}
else 1
}
Ответ №6:
Используйте lapply
функцию после создания вашей функции в обычном режиме.
lapply(x="your input", fun="insert your function name")
lapply
выдает список, поэтому используйте unlist
функцию, чтобы удалить их из функции
unlist(lapply(a,w))
Комментарии:
1. Вы имеете в виду
unlist
удаление его из списка, а не функции?2. да, я это имел в виду, извините за ошибку
Ответ №7:
Я бы сказал, что наиболее эффективным способом является ответ пользователя 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
}