Reputation: 1273
Let's say I have a vector drawn from a normal distribution.
RandomVector<-rnorm(10,mean=1,sd=1)
> RandomVector
[1] 1.18186018 0.53810223 0.33888370 0.46593762 2.33963330 -0.08779368 -0.65178144 -0.61384231 -0.74351425
[10] -0.51577616
I want to find the position of the first number <=0 in the vector. The simplest way would be to use which.
FirstNegative<-min(which(RandomVector<=0))
However, in some cases the vector may have no negative numbers, in which case which( ) will return a vector of length zero.
> RandomVector
[1] 1.20150245 0.58668248 1.65633049 1.63277953 0.51134272 0.76385987 0.89085391 0.06504819 0.18011920 0.02400666
This will give you an error.
> FirstNegative<-min(which(RandomVector<0))
Warning message:
In min(which(RandomVector < 0)) :
no non-missing arguments to min; returning Inf
Here are some solutions to this problem that I've come up with. All of them work, but I want to avoid an if/else statement if possible. Can anyone think of a more concise way?
for (j in 1:length(RandomVector)) {
if (RandomVector[j]<=0) {
FirstNegative<-j
break;
}
Alternatively...
WhichNegative<-which(RandomVector<=0)
if (length(WhichNegative)>0) {
FirstNegative<-min(WhichNegative)
}
Same basic idea, but still using an if statement
if (any(RandomVector<=0)==TRUE) {
FirstNegative<-min(which(RandomVector<=0))
}
The reason I'm asking is because this check will be made for a large number of vectors of long length. Plus I'm just curious.
Upvotes: 3
Views: 7788
Reputation: 3317
Solution
You can use:
FirstNegative <- which(RandomVector <= 0)[1]
Which will return the position of the first element less than or equal to zero, or NA
if nothing is applicable. You can then catch the NA
and do whatever you would like.
Comment
The reason min
returns an error is because it expects an input of length greater than zero.
Your first method of searching for the first negative is quite computationally expensive, as you may have to go through every element of the vector. Binomial search may be a quicker method.
The second and third methods are fine, the second will be quicker than the third as in the third you will go through the vector twice, once to find any element less than or equal to zero, then to find the first.
Ultimately though, the method given in solution will be quickest, as which
returns a sorted list, and therefore min
doesn't do anything useful as the minimum will always be the first element.
Upvotes: 10