#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 butif
операторы могут быть полезны, но … им нужно сделать что-то еще.)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 действительно «вознаграждает» выполнение целых векторов за раз, поэтому первые три используют преимущества «векторизации»:
-
Поскольку вы смотрите на определенную длину значений (
range
offj.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"
-
Вы можете предварительно заполнить
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"
-
Хотя мне обычно не очень нравится вложенность
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"
-
Наконец, цикл перебора
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
их использовать.