Цикл с тремя условиями в R

#r

#r

Вопрос:

Извините, если я ввел неправильный заголовок, я новичок в программировании, прошу прощения за любые неудобства. Я хочу сравнить каждое значение в nutl с диапазоном значений в fj.ru, выходные данные должны возвращать: если значение находится в пределах от 4 до 7, вывод должен быть в пределах предела, если значение больше 7, то оно должно возвращать избыточное, если меньше, то оно должно выводить недостаточное. Я знаю, что не могу провести векторное сравнение для его внутренних данных, но как я могу заставить его это сделать? Я попробовал следующее:

 nutl<-c(7,3,5,6,10,5,6)
nutl
fj.en <- c(4:7)
fj.en
for (refnut in nutl) {
    if (refnut == fj.en) {
    print ("winthin limit")
    if (refnut > fj.en) {
    print ("excessive")
    }
    else {
    print ("insufficient")
    }
}
    }
  

Комментарии:

1. (1) Я склонен считать if / else with nothing but print statements пустой тратой времени: вы прилагаете все эти усилия, и ничто из того, что вы сделали, нигде не хранится или иным образом не может быть использовано за пределами человека, читающего консоль. (Вложенные if операторы могут быть полезны, но … им нужно сделать что-то еще.)

2. (2) if требует условия длиной ровно 1, и ни одно из ваших не похоже на это. Когда я спрашиваю вас: «4 равно 3, 4, 5, 6» , вы можете ответить что-то вроде «это равно одному из них» ; оттуда следует рассмотреть возможность использования any , all , %in% , или какой-либо другой логики. Я бы предложил что-то более конкретное, но мне не ясно, какова ваша цель здесь.

3. Возможно, вы просто хотите ifelse(refnut == fj.en, "within limit", ifelse(refnut > fj.en, "excessive", "insufficient")) ?

4. @r2evans Я только что обновил, какова цель, спасибо, что указали, что я должен уточнить цель.

Ответ №1:

Существует несколько способов решения этой проблемы, причем for цикл является наименее эффективным. R действительно «вознаграждает» выполнение целых векторов за раз, поэтому первые три используют преимущества «векторизации»:

  1. Поскольку вы смотрите на определенную длину значений ( range of fj.en ), тогда мы можем использовать findInterval или cut (здесь):

     as.character(cut(nutl, c(-Inf, range(fj.en), Inf), labels = c("insufficient", "within limit", "excessive")))
    # [1] "within limit" "insufficient" "within limit" "within limit" "excessive"   
    # [6] "within limit" "within limit"
      
  2. Вы можете предварительно заполнить character вектор и заполнить их вручную:

     out <- character(length(nutl))
    out[ nutl < min(fj.en) ] <- "insufficient"
    out[ nutl > max(fj.en) ] <- "excessive"
    out[ !nzchar(out) ] <- "within limit"
    out
    # [1] "within limit" "insufficient" "within limit" "within limit" "excessive"   
    # [6] "within limit" "within limit"
      

    !nzchar(.) Функция ищет строки нулевой длины. character(.) предварительно заполняет вектор "" строк (нулевой длины) до запрошенной длины, поэтому мы знаем, что первые два переназначения назначили строки с более чем 0 символами, поэтому !nzchar сработали. Это также было бы хорошо сделать

     out[ min(fj.en) <= nutl amp; nutl <= max(fj.en) ] <- "within limit"
      
  3. Хотя мне обычно не очень нравится вложенность ifelse , двухмерная глубина не является большой проблемой:

     ifelse(nutl < min(fj.en), "insufficient",
           ifelse(nutl > max(fj.en), "excessive", "within limit"))
    # [1] "within limit" "insufficient" "within limit" "within limit" "excessive"   
    # [6] "within limit" "within limit"
      
  4. Наконец, цикл перебора for .

     out <- character(length(nutl))
    for (ind in seq_along(nutl)) {
      if (nutl[ind] < min(fj.en)) {
        out[ind] <- "insufficient"
      } else if (nutl[ind] > max(fj.en)) {
        out[ind] <- "excessive"
      } else out[ind] <- "within limit"
    }
    out
    # [1] "within limit" "insufficient" "within limit" "within limit" "excessive"   
    # [6] "within limit" "within limit"
      

Я демонстрирую еще одну рекомендацию: сохраните значения (в предварительно выделенном векторе, если это необходимо), а затем определите, хотите ли вы print их использовать.