0

Please can anyone advise how I can turn the following statement into one that will do the same thing but NOT using ifelse please?

<-ifelse(y>=50, 0.2*x+0.8*y, ifelse(y<50 & x>70, y+10, ifelse(y<50 & x<70, y))) 

x=80
y=60

So I the final code should give an answer of 64 - selecting the first condition. I will then test it to ensure the other 3 conditions give the correct result for varying values of x and y

Thanks a lot.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • What's the problem with this code? – Arun Feb 06 '13 at 12:44
  • 2
    What's up with `ifelse`? Is `y` a vector? Is `if` and `else` a suitable alternative to `ifelse`? – user1317221_G Feb 06 '13 at 12:44
  • 3
    Why didn't you accept any of the answers to your similar question? http://stackoverflow.com/questions/14713330/chaining-multiple-logical-operator What's the problem with `ifelse`? – Sven Hohenstein Feb 06 '13 at 12:49
  • 2
    Yes, vote up and accept answers or people will stop giving them to you. – John Feb 06 '13 at 13:29
  • Looking at the previously posted question, it looks like the OP's problem is more one of approach. It sounds like the reason to pack everything into one line, is that the OP isn't aware of how to create a function to loop through or how to create a single vectorized command to do it all at once. Perhaps the question being asked does not lead to the answer the OP needs. – Dinre Feb 06 '13 at 13:46
  • I suspect the OP will be a lot happier in the long run learning to use `switch` . The advantage here is that she can easily change the cutoff points or the `y` - manipulations. – Carl Witthoft Feb 06 '13 at 14:12
  • OP: please make it clear your intent is to get equivalent ifelse functionality using logical operators, for verifying the ifelse expression. – smci Mar 27 '14 at 13:39
  • @Carl-Witthoft, switch is pretty nasty, it doesn't vectorize, and all subexpressions need to evaluated, non-lazily? – smci Mar 27 '14 at 13:41
  • @smci, `switch` is rather handy, and you can't vectorize a series of if...else anyway (except in specialized cases), and switch stops at the first satisfied condition (check the manual). – Carl Witthoft Mar 27 '14 at 21:35
  • But **all** subexpressions need to evaluated, non-lazily, first, before you select which one, right? And for k sub-expressions * length n, that could get expensive. – smci Mar 28 '14 at 05:28

4 Answers4

4

This should work:

finalmark <- (x * 0.2 + y * 0.8) * (y >= 50) + (y + 10 * (x > 70)) * (y < 50)
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
  • Ha! I didn't know FALSE returned a numerical zero in R. Brilliant, sir. The drawback is that you always have to make each logical comparison for each set of numbers, but the advantage is that you remove the logic blocks. In some cases, this would be lightning fast... I will have to add this to my regular set of tools. – Dinre Feb 06 '13 at 13:34
  • Hi,That's great thank-you. As soon as you mentioned this I realised I'd been making things far too complicated for myself – Tanya Kiddle Feb 07 '13 at 21:22
  • @Dinre and others: the downside compared to `ifelse` is that all subexpressions will be evaluated, there's no lazy evaluation. – smci Mar 27 '14 at 13:37
1

Something like this?

if(y>=50){
    0.2*x+0.8*y 
     }else{
      if(y<50 & x>70){
         y+10 
          }else{ 
            if(y<50 & x<70){
               y 
              }else{
               "OMG I did not expect this scenario"
            }
        }
    }

try: y=45; x=70 to see why I have the last condition.

user1317221_G
  • 15,087
  • 3
  • 52
  • 78
  • 1
    +1 for "OMG..." :-) Although the correct formulation, according to thedailywtf.com , would be more like "This Should Never Happen [OK box]" – Carl Witthoft Feb 06 '13 at 14:58
1

If y is a number then, once you've tested for y > = 50 then y must be less than 50 so don't keep testing for that. Similarly, once you've found x > 70 then you don't need the last ifelse. You don't have a return for x = 70. My guess is that you want to test for a <= or >= situation there.

ifelse(y>=50, 0.2*x+0.8*y, ifelse(x>70, y+10, y)) 

in scalar that's

if(y >= 50){
  0.2*x+0.8*y
}else if(x > 70){
  y+10
}else y

Given you seem to be having a hard time in general writing the logic I suggest you post a more complete question. It's possible (probable) that you're doing something here that you really don't want to do.

John
  • 23,360
  • 7
  • 57
  • 83
0

There are several approaches you can take. Below are a few examples of building a function 'f', so that 'f(x,y)' meets your criteria listed in the question using logic other than 'ifelse' statements. Note: I'm also adding in one amendment to the original post, since 'x=70' would break the logic. I'm adding 'x>=70' to the second criterion.

Option 1: Use a standard 'if / else if / else' logic block. Personally, I like this option, because it's easily readable.

f <- function(x, y){
    if (y>= 50){
        return(0.2*x+0.8*y)
    } else if (y < 50 & x >= 70){
        return(y+10)
    } else {
        return(y)
    }
}

Option 2: Combine your two logical tests (there are really only two) into a string, and use a switch. Note that the final and unnamed option is treated as an 'else'.

f <- function(x, y){
    return(
        switch(paste(x >= 70, y >= 50, sep=""), 
            TRUEFALSE = y + 10, 
            FALSEFALSE = y,
            0.2*x+0.8*y 
        )
    )
}

Option 3: Order your 'if' statements to reduce logical comparisons. This is the sort of thing to do if you have a large data set or very limited memory. This is slightly harder to troubleshoot, since you have to read the whole block to fully understand it. Option 1 is better if you don't have memory or cycle limitations.

f <- function(x, y){
    if (y >= 50){
        return(0.2*x+0.8*y)
    } else {
        if (x >=70){
            return(y+10)
        } else {
            return(y)
        }
    }
}

There are other options, but these are the simplest that come readily to mind.

Dinre
  • 4,196
  • 17
  • 26