Use of IF function in R

61,056

Solution 1

if() expects whetever is in the parentheses to evaluate to a logical vector of length 1 (TRUE or FALSE). If the vector is longer than 1, then as the warning says only the first element of the vector is used.

An alternative if ifelse() where it is used as :

ifelse(test, TRUE_CASE, FALSE_CASE)

For your example we have:

set.seed(1)
ifelse(runif(50, 0, 1) < 0.69, rnorm(50, 25, 4), rnorm(50, 28, 4.3))

or

set.seed(1)
test <- runif(50, 0, 1)
Tcase <- rnorm(50, 25, 4)
Fcase <- rnorm(50, 28, 4.3)
ifelse(test, Tcase, Fcase)

Either is OK as ifelse() generates the two vectors for TRUE_CASE and FALSE_CASE before doing the comparisons.

Example output is:

R> ifelse(test < 0.69, Tcase, Fcase)
 [1] 24.77549 24.37682 19.11699 28.31967 26.67177 25.55472 27.41873 26.55069
 [9] 24.78478 19.49176 23.34002 23.42284 24.76275 29.40010 29.14852 24.34191
[17] 33.19383 32.98973 27.22665 34.82338 30.40149 26.45833 28.07413 24.55062
[25] 28.52443 26.59242 22.55189 26.36448 28.67952 30.73209 32.92160 23.53111
[33] 20.82346 27.27888 35.23336 34.60647 26.01493 27.75896 25.20201 22.02691
[41] 26.31093 17.78017 26.79981 25.61301 33.69045 25.82438 22.16021 27.44291
[49] 27.22791 27.56918

Another way is to do this is to only generate the required values

want <- test < 0.69
res <- test ## copy vector of correct length
res[want] <- rnorm(S <- sum(want), 25, 4)
res[!want] <- rnorm(length(res) - S, 28, 4.3)

R> res
 [1] 27.85067 24.70574 24.84946 22.04696 22.27336 36.03795 29.82793 23.70292
 [9] 25.24064 22.64442 27.12598 18.92642 26.22623 18.85420 26.97382 23.79610
[17] 32.55148 31.81162 22.88688 25.33725 37.48624 22.39162 24.77241 17.34256
[25] 29.70633 18.34011 23.14588 20.53632 26.90338 21.99672 33.34867 25.06958
[33] 19.85480 18.43758 21.87467 26.80075 27.37908 24.92576 28.89241 23.72773
[41] 37.92431 21.28255 28.45495 19.05016 20.69923 29.96509 29.00012 22.51493
[49] 27.66824 26.56380

That obviously gives different numbers to the previous ones but only because we generated fewer random numbers. I doubt this will be any more efficient than ifelse() for most problems.

Solution 2

You need any or all, which convert a vector of logicals into a single logical (well, actually a vector of length 1).

Share:
61,056
YesSure
Author by

YesSure

Updated on August 02, 2020

Comments

  • YesSure
    YesSure almost 4 years

    I am running a short if function in R but am getting the following warning message:

    In if ((runif(50, 0, 1) < 0.69)) { :  the condition has length > 1 and only the first element will be used`. 
    

    My rudimentary grasp of R leads me to believe that runif generates a vector but if yields a single value, so I'm thinking this is the issue. Is there any simple substitution for if here?

    Also i want the end product to be a matrix combination of the two arguments but i wasn't sure if it was correct to put 50 in the rnorm function for both scenarios.

    Test <-
     if((runif(50, 0, 1)<0.69)) {
     rnorm(50, 25, 4)
     } else {
     rnorm(50, 28, 4.3)
    }