ЕСЛИ операторы в R - всегда вложенные? - PullRequest
2 голосов
/ 22 января 2012

Я только сейчас начинаю погружаться в IF операторы в R.Из того, что я вижу из документации CRAN об операторах IF , видно, что все операторы IF должны быть nested.

Это правда?Если это так, эта IF/THEN структура больше похожа на EXCEL и, я думаю, не так прямолинейна, как RUBY или Python IF/THEN логика.Разве я не прерываю это правильно?

В EXCEL (графический интерфейс, а не VBA) вы должны запустить формулу, подобную этой:

#IF Statement 1
=IF(A1<20, A1*1, 
#IF Statement 2
IF(A1<50, A1*2,
#IF Statement 3
IF(A1<100, A1*3, A1*4)
#Closes IF Statement 2
)
#Closes IF Statement 1
) 

Nested IF/THEN сложны, потому чтоВы должны убедиться, что закрыли функции должным образом.

Эта следующая часть - я не уверен на 100%, так как я новичок в обоих языках, но ... В Ruby или Python вы можете явно написать функцию IFболее структурированным образом:

IF 
ELSE
END

Это намного проще и понятнее.

Мне не хватает подходящего способа запустить это в R, или это так сложно?Есть ли хороший ресурс, который я еще не нашел на IF / THEN / Loop для R?

Спасибо

Ответы [ 3 ]

7 голосов
/ 22 января 2012

На самом деле в R. есть две формы if-else логики управления потоком, доступной в R.

Оператор if в первом приближении очень похож на C, C ++ или Java if.Как и в этих языках, вы можете последовательно соединять if s.

if(test) {
    statements
}
else if(test2) {
    statements
}
else {
    statements
}

R также имеет функцию ifelse, которая действительно очень похожа на =IF в Excel.Грубый эквивалент приведенного выше if-elseif-else будет

ifelse(test, result1, ifelse(test2, result2, result3))

Ключевое отличие состоит в том, что во втором примере test, result1, result2 и result3 являются векторами.

Вы должны использовать первое, если хотите выполнить такой же набор операций для всего набора данных, но , который устанавливается в зависимости от теста.Второй предназначен для векторизованных вычислений, где вы хотите выполнить различных операций с каждым элементом вектора.

6 голосов
/ 22 января 2012

Многие новые пользователи R сбиты с толку по поводу if. Он оценивает только одно значение и затем выполняет либо следующее выражение, либо предложение else. В R функция ifelse, как правило, нужна бывшим пользователям SAS, Excel и SPSS, и она поддерживает вложение. Существует функция switch, которая может быть полезна в некоторых случаях, хотя я не вижу, как ваш набор неисключительных логических условий сразу вписался бы в ее логику.

В вашем случае я бы подумал об использовании функции findInterval. Это выполнит объединенные операции логической и математической операции в вашем примере (и вернет вектор, если «A» был вектором):

A*( 1+ findInterval( A, c(20,50,100) )  )  # OR 
A*( 1+ findInterval( A, c(-Inf, 20, 50, 100) )  ) # the equivalent using -Inf

И немного подумав об этом. Функцию findInterval можно также использовать в качестве первого аргумента для switch, если вы хотите, чтобы функция применялась к "A".

(Дальнейший комментарий: я предполагал, что ваше выражение «A1» будет скопировано вниз по столбцу или строке ячеек в электронной таблице Excel и будет в процессе увеличивать ссылки на строки или столбцы определенным автоматическим способом, который поддерживает Excel становится A2, A3 и т. д. Это другая точка зрения программирования, чем любой из более общих языков, с которыми вы сравниваете. Операции над векторами R аналогичны, но обычно не требуют "1", "2", "3". . записи и поэтому я пропустил их из кода.)

6 голосов
/ 22 января 2012

Я не уверен, что понимаю вопрос, но натуральный R-эквивалент вашего кода Excel будет

if (a1 < 20)
  a1 * 1
else if (a1 < 50)
  a1 * 2
else if (a1 < 100)
  a1 * 3
else
  a1 * 4

И вы можете поставить фигурные скобки вокруг выражений a1 * n, если хотите. Однако, если a1 является вектором, а не скаляром, вы, вероятно, захотите оценить сравнение параллельно для всех векторных элементов, что делается с помощью ifelse, который делает вложенным, как ваша конструкция Excel:

ifelse(a1 < 20, a1 * 1,
       ifelse(a1 < 50, a1 * 2,
              ifelse(a1 < 100, a1 * 3,
                               a1 * 4)))

Третий способ записать его для вектора a1 использует преимущества логической индексации:

a2 <- a1 # take a copy
a2[a1 >=  20 & a1 <  50] <- a1[a1 >=  20 & a1 <  50] * 2
a2[a1 >=  50 & a1 < 100] <- a1[a1 >=  50 & a1 < 100] * 3
a2[a1 >= 100           ] <- a1[a1 >= 100           ] * 4
...