从`if`函数解释“condition has length> 1”警告

时间:2013-01-05 10:12:23

标签: r

我有一个数组:

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

如何更正功能?

6 个答案:

答案 0 :(得分:50)

也许你想要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 :(得分:37)

if语句未向量化。对于vectorized if语句,您应该使用ifelse。在你的情况下,写

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

或简短的矢量化版本

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

这取决于你想要使用哪个,因为第一个函数给出长度为1的输出向量(在其他部分),ifelse给出长度等于a长度的输出向量。

答案 2 :(得分:16)

这是一种没有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

答案 3 :(得分:13)

只是在整个讨论中添加一个观点,说明为什么会出现此警告(之前我不清楚)。之前提到的原因是因为在这种情况下'a'是向量而不等式'a&gt; 0'产生另一个TRUE和FALSE向量(其中'a'是> 0或不是)。

如果您想测试是否有'a&gt; 0'的任何值,您可以使用函数 - 'any'或'all'

最佳

答案 4 :(得分:2)

我解决这个问题的方式是当我尝试做类似的事情时,我在定义一个函数,并且像其他人指出的那样用数组调用

你可以做这样的事情但是对于这种情况来说,与Sven的方法相比它不那么优雅。

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

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

答案 5 :(得分:1)

正常创建函数后,请使用lapply函数。

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

lapply给出了一个列表,因此请使用unlist函数将其从函数中删除

unlist(lapply(a,w))