Как получить эквивалент функциональности R ifelse, используя логические операторы

Пожалуйста, кто-нибудь может посоветовать, как я могу превратить следующий оператор в тот, который будет делать то же самое, но НЕ используя ifelse, пожалуйста?

<-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

Так что я окончательный код должен дать ответ 64 - выбор первого условия. Затем я проверю его, чтобы убедиться, что другие 3 условия дают правильный результат для различных значений x и y.

Большое спасибо.


person Tanya Kiddle    schedule 06.02.2013    source источник
comment
В чем проблема с этим кодом?   -  person Arun    schedule 06.02.2013
comment
Что случилось с ifelse? Является ли y вектором? Являются ли if и else подходящей альтернативой ifelse?   -  person user1317221_G    schedule 06.02.2013
comment
Почему вы не приняли ни один из ответов на ваш аналогичный вопрос? stackoverflow.com/questions/14713330/ В чем проблема с ifelse?   -  person Sven Hohenstein    schedule 06.02.2013
comment
Да, проголосуйте и примите ответы, иначе люди перестанут давать их вам.   -  person John    schedule 06.02.2013
comment
Глядя на ранее опубликованный вопрос, похоже, что проблема ОП больше связана с подходом. Похоже, причина упаковать все в одну строку заключается в том, что ОП не знает, как создать функцию для цикла или как создать единую векторизованную команду, чтобы сделать все это сразу. Возможно, заданный вопрос не приводит к ответу, который нужен ОП.   -  person Dinre    schedule 06.02.2013
comment
Я подозреваю, что в конечном итоге ОП будет намного счастливее научиться использовать switch . Преимущество здесь в том, что она может легко менять точки отсечки или y - манипуляции.   -  person Carl Witthoft    schedule 06.02.2013
comment
OP: пожалуйста, дайте понять, что вы намерены получить эквивалентную функциональность ifelse с помощью логических операторов для проверки выражения ifelse.   -  person smci    schedule 27.03.2014
comment
@ Карл-Витхофт, переключатель довольно неприятный, он не векторизуется, и все подвыражения нужно оценивать не лениво?   -  person smci    schedule 27.03.2014
comment
@smci, switch довольно удобен, и вы все равно не можете векторизовать серию if ... else (за исключением особых случаев), а переключатель останавливается при первом выполненном условии (проверьте руководство).   -  person Carl Witthoft    schedule 28.03.2014
comment
Но все подвыражения должны быть оценены, не лениво, сначала, прежде чем вы выберете, какое из них, верно? А для k подвыражений * длины n это может дорого обойтись.   -  person smci    schedule 28.03.2014


Ответы (4)


Это должно работать:

finalmark <- (x * 0.2 + y * 0.8) * (y >= 50) + (y + 10 * (x > 70)) * (y < 50)
person Sven Hohenstein    schedule 06.02.2013
comment
Ха! Я не знал, что FALSE возвращает числовой ноль в R. Гениально, сэр. Недостаток в том, что вам всегда нужно делать каждое логическое сравнение для каждого набора чисел, но преимущество в том, что вы удаляете логические блоки. В некоторых случаях это было бы молниеносно... Мне придется добавить это к моему обычному набору инструментов. - person Dinre; 06.02.2013
comment
Привет! Большое спасибо. Как только вы упомянули об этом, я понял, что слишком все усложнял для себя. - person Tanya Kiddle; 08.02.2013
comment
@Dinre и другие: недостатком по сравнению с ifelse является то, что будут оцениваться все подвыражения, ленивых вычислений нет. - person smci; 27.03.2014

Что-то вроде этого?

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"
            }
        }
    }

попробуйте: y=45; x=70 чтобы понять, почему у меня последнее условие.

person user1317221_G    schedule 06.02.2013
comment
+1 за OMG... :-) Хотя правильная формулировка, согласно thedailywtf.com, была бы больше похожа на Это никогда не должно происходить [ОК поле] - person Carl Witthoft; 06.02.2013

Если y — это число, то после проверки y > = 50 значение y должно быть меньше 50, поэтому не продолжайте проверку на это. Точно так же, как только вы нашли x > 70, вам не нужен последний ifelse. У вас нет возврата для x = 70. Я предполагаю, что вы хотите проверить ситуацию ‹= или >=.

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

в скаляре это

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

Учитывая, что вам, похоже, трудно вообще написать логику, я предлагаю вам опубликовать более полный вопрос. Возможно (вероятно), что вы делаете здесь что-то, чего на самом деле делать не хотите.

person John    schedule 06.02.2013

Есть несколько подходов, которые вы можете предпринять. Ниже приведены несколько примеров построения функции «f», чтобы «f (x, y)» соответствовало вашим критериям, указанным в вопросе, с использованием логики, отличной от операторов «ifelse». Примечание. Я также добавляю одну поправку к исходному сообщению, так как "x=70" нарушит логику. Я добавляю "x>=70" ко второму критерию.

Вариант 1. Используйте стандартный логический блок if / else if / else. Лично мне этот вариант нравится, потому что он легко читается.

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)
    }
}

Вариант 2. Объедините два логических теста (на самом деле их всего два) в строку и используйте переключатель. Обратите внимание, что последняя и безымянная опция рассматривается как «еще».

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

Вариант 3. Упорядочите операторы if, чтобы уменьшить количество логических сравнений. Это то, что нужно делать, если у вас большой набор данных или очень ограниченная память. Это немного сложнее устранить, так как вам нужно прочитать весь блок, чтобы полностью понять его. Вариант 1 лучше, если у вас нет ограничений по памяти или циклу.

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

Есть и другие варианты, но это самые простые, которые приходят на ум.

person Dinre    schedule 06.02.2013