Создание цикла для сегментов в векторе, которые дают возвращаемые значения для каждого соответствующего сегмента - PullRequest
0 голосов
/ 21 февраля 2019

Я создал вектор «numGrades» из 100 случайных чисел для представления значений в системе оценок.Мне нужно написать цикл «для», который принимает сегменты числовых оценок и возвращает вектор соответствующих буквенных оценок, то есть: 90+ = "A", 80-89 = "B", 70-79 = "C", 60-69 = "D", 0-59 = "F".Я хочу иметь возможность запускать numGrades для возврата соответствующей буквенной оценки, например: numGrades = [72, 65, 93] returning = ["C", "D", "A"] с векторами обработки цикла любой длины. Это то, что я пробовал до сих пор индивидуально.Все эти циклы возвращают предупреждения:

set.seed(43)
numGrades <- sample(0:100, 100, replace=FALSE)

for (i in numGrades )
  if(91 <= numGrades[i]) {
    numGrades[i] <- "A"
  } else if (80 <= numGrades[i] & numGrades[i] <= 90) {
    numGrades[i] =="B"
  } else if (70 <= numGrades[i] & numGrades[i] <= 79) {
    numGrades[i] =="C"
  } else if (60 <= numGrades[i] & numGrades[i] <= 69) {
    numGrades[i] =="D"
  } else if (0 <= numGrades[i] & numGrades[i] <= 59) {
    numGrades[i] =="F"
  }

Это говорит:

Error in if (91 <= numGrades[i]) { : 
  missing value where TRUE/FALSE needed

Новое редактирование (Возвращает только для классов> = 91):

numGrades <- (0:100)
for (i in 1:length(numGrades ))
  if(91 <= numGrades[i]) {
    numGrades[i] <- "A"
  } else if (80 <= numGrades[i] & numGrades[i] <= 90) {
    numGrades[i] =="B"
  } else if (70 <= numGrades[i] & numGrades[i] <= 79) {
    numGrades[i] =="C"
  } else if (60 <= numGrades[i] & numGrades[i] <= 69) {
    numGrades[i] =="D"
  } else if (0 <= numGrades[i] & numGrades[i] <= 59) {
    numGrades[i] =="F"
  }

Рабочий грубый осадок

ltrGrades <- (0:100)
numGrades <- character(length(ltrGrades))

for (i in 1:length(ltrGrades ))
  if(any(ltrGrades[i] == 91:100)) {
    numGrades[i] <- "A"
  } else if (any(ltrGrades[i] == 80:90)) {
    numGrades[i] <- "B"
  } else if (any(ltrGrades[i] == 70:79)) {
    numGrades[i] <- "C"
  } else if (any(ltrGrades[i] == 60:69)) {
    numGrades[i] <- "D"
  } else if (any(ltrGrades[i] == 0:59)) {
    numGrades[i] <- "F"
  }

1 Ответ

0 голосов
/ 21 февраля 2019

Существуют некоторые фундаментальные проблемы с синтаксисом R в вашем коде.

(numGrades[i]) c(80:90))
(numGrades[i]) >=80 && <=89)
(numGrades[i]) ==80:89 )

Несколько альтернатив, наиболее неэффективных:

(80 <= numGrades[i] & numGrades[i] < 90)    # the most basic
(dplyr::between(numGrades[i], 80, 90))      # if dplyr is loaded
(data.table::between(numGrades[i], 80, 90)) # if data.table is available
(numGrades[i] %in% 80:89)                   # works only if all grades are perfectly integral
(any(numGrades[i] == 80:89))                # ditto

Почему они неверны?

  • (numGrades[i]) c(80:90)), поскольку нет оператора
  • (numGrades[i]) >=80 && <=89), R не выводит их, как вы предлагаете, каждый раз, когда вы делаете (в) тесте на равенство, вам нужно указать как LHS, так и RHS длякаждый;аналогично, в отличие от многих языков, R не «цепляет» их, поэтому (80 <= numGrades[i] <= 89) не будет работать
  • (numGrades[i]) ==80:89 ) приближается, но операторы if / else требуют одного сравнения;в этом случае вы сравниваете одно число с последовательностью (диапазоном) из 10, поэтому ответом будет длина 10. Длина должна быть 1.

Суть в том, что выне нужен цикл.

# set.seed(43)
numGrades <- sample(0:100, 100, replace=FALSE)
cut(numGrades, c(-1, 60, 70, 80, 90, 101), labels=c("F","D","C","B","A"))
#   [1] F A F D F F D F F C F F F F F B F A F F C A F F F F A F A F C C C B F
#  [36] F F F B A F F F A B B C D F F F B D F F B D D B F F F F F F D F A F F
#  [71] F F F F B F D F A F F F F F A B F F F C F F F D D C C F F F
# Levels: F D C B A

или если вам не нравится или не понимает, что такое factor, тогда

as.character(cut(numGrades, c(-1, 60, 70, 80, 90, 101), labels=c("F","D","C","B","A")))
#   [1] "F" "A" "F" "D" "F" "F" "D" "F" "F" "C" "F" "F" "F" "F" "F" "B" "F"
#  [18] "A" "F" "F" "C" "A" "F" "F" "F" "F" "A" "F" "A" "F" "C" "C" "C" "B"
#  [35] "F" "F" "F" "F" "B" "A" "F" "F" "F" "A" "B" "B" "C" "D" "F" "F" "F"
#  [52] "B" "D" "F" "F" "B" "D" "D" "B" "F" "F" "F" "F" "F" "F" "D" "F" "A"
#  [69] "F" "F" "F" "F" "F" "F" "B" "F" "D" "F" "A" "F" "F" "F" "F" "F" "A"
#  [86] "B" "F" "F" "F" "C" "F" "F" "F" "D" "D" "C" "C" "F" "F" "F"

РЕДАКТИРОВАТЬ

Я только что заметил кое-что еще о вашем коде.

При запуске numGrades является либо числовым, либо целым числом.Однако, поскольку это вектор, при первом назначении буквы одному из его элементов весь вектор преобразуется в вектор character.При повторном прохождении цикла for будет пытаться сравнить число со строкой, которая не будет выполнять числовое сравнение, попробуйте 8 < "75", чтобы выяснить, почему это не удастся.

В качестве обходного пути для этого:

ltrGrades <- character(length(numGrades))
for (i in 1:length(numGrades ))
  if(91 <= numGrades[i]) {
    ltrGrades[i] <- "A"
  } else if (80 <= numGrades[i] & numGrades[i] <= 90) {
    ltrGrades[i] <- "B"
  } else if (70 <= numGrades[i] & numGrades[i] <= 79) {
    ltrGrades[i] <- "C"
  } else if (60 <= numGrades[i] & numGrades[i] <= 69) {
    ltrGrades[i] <- "D"
  } else if (0 <= numGrades[i] & numGrades[i] <= 59) {
    ltrGrades[i] <- "F"
  }
...