Оператор IF с несколькими условиями, всегда говорящий true (вложенный в цикл while)

#r

#r

Вопрос:

Пожалуйста, посмотрите мой код ниже.

У меня есть фрейм данных, где каждая раса, с которой идентифицируется человек, находится в столбце (например. AWHITE, ABLACK и т.д.) И если они идентифицируют себя с этой гонкой, тогда запись равна 1 (если нет, запись равна 2). Респонденты могут идентифицировать себя с более чем одной расой.

Я пытаюсь определить, когда респондент заявил, что он принадлежит более чем к одной расе. Если они это сделают, я хочу, чтобы один столбец (ARACE) обновился до 91, а другой столбец (AOTHRACE) стал 2.

Оператор if (в приведенном ниже коде) всегда принимает значение TRUE. Даже если это неверно. Есть респонденты, которые идентифицируют себя только как одна раса (т. е. белые). Я просматривал это несколько раз, но не могу найти, где я напортачил.

Я планирую использовать больше операторов if (if, else if) также для других рас / столбцов (т. Е. респондент идентифицирует себя как черный И по крайней мере одну другую расу), но я не могу заставить работать даже первый, поэтому я этого не реализовал.

(На самом деле я не хочу, чтобы else было равно 0, я просто использовал это, чтобы подтвердить, что код работает не так, как ожидалось. Когда я запускал итоговую функцию в ARACE, минимум был 91, поэтому я знаю, что это утверждение никогда не оценивалось.)

 i <- 0
while (i <= nrow(nhes05v2)){
  if ((nhes05v2$AWHITE == 1) amp;amp; (any(nhes05v2$ABLACK==1, nhes05v2$AAMIND==1, nhes05v2$AASIAN==1, nhes05v2$APACI==1))){
    nhes05v2$ARACE = 91
    nhes05v2$AOTHRACE = 2}
  else {nhes05v2$ARACE = 0
  nhes05v2$AOTHRACE = 0}
  i <- i 1}
  

Вот пример значений:

 > nhes05v2$AWHITE[1:20]
 [1] 1 1 1 1 1 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1
> nhes05v2$ABLACK[1:20]
 [1] 2 1 2 2 2 2 1 1 1 2 2 1 2 2 2 2 2 2 2 2
> nhes05v2$AASIAN[1:20]
 [1] 2 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2
> nhes05v2$AAMIND[1:20]
 [1] 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2
> nhes05v2$APACI[1:20]
 [1] 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2
  

Я хотел бы, чтобы результат был чем-то вроде (это было бы не только с одним моим оператором if выше, было бы больше if, else if , но поскольку я застрял на первом, я не прошел мимо этого)

 > nhes05v2$ARACE[1:20]
 [1] 0 91 0 91 0 91 91 0 0 91 0 0 0 0 0 0 0 0 0 0
> nhes05v2$AOTHRACE[1:20]
 [1] 0 2 0 2 0 2 2 0 0 2 0 0 0 0 0 0 0 0 0 0
  

В настоящее время вывод является

 > nhes05v2$ARACE[1:20]
 [1] 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91
> nhes05v2$AOTHRACE[1:20]
 [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
  

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

1. Ваши переменные race ( AWHITE , ABLACK AAMIND и т.д.) кодируются как числовые или факторные уровни?

2. Ваш код не воспроизводим и не поддается тестированию. Пожалуйста, поделитесь воспроизводимым примером вашего фрейма данных и ожидаемым результатом. Вполне вероятно, что нам не нужны никакие циклы for или while для выполнения вашей задачи.

3. @NM_ в данный момент они числовые

4. @www Я отредактировал, чтобы добавить некоторый контекст. Спасибо вам обоим за ваши отзывы!

5. Возможно ли, чтобы кто-то принадлежал к более чем одной расе, принадлежать к двум небелым расам (например, азиатской и черной)? Это потому, что ваш текущий оператор if считает, что человек принадлежит более чем к одной расе, если он белый по крайней мере еще одна раса (т. Е. для того, чтобы быть смешанным, они должны быть белыми какой-то другой расы).

Ответ №1:

Мы можем достичь этого, перекодировав значение 2 в 0 (т.е. 0 = «Нет») и используя следующий код с двумя функциями, используемыми для определения, удовлетворяет ли запись критериям.

Пожалуйста, обратите внимание, что код предполагает, что переменные race являются числовыми.

 # Replicate your example
AWHITE = as.numeric(unlist(strsplit("1 1 1 1 1 1 2 2 2 1 1 2 1 1 1 1 1 1 1 1", " ")))
ABLACK = as.numeric(unlist(strsplit("2 1 2 2 2 2 1 1 1 2 2 1 2 2 2 2 2 2 2 2", " ")))
AASIAN = as.numeric(unlist(strsplit("2 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2", " ")))
AAMIND = as.numeric(unlist(strsplit("2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2", " ")))
APACI = as.numeric(unlist(strsplit("2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2", " ")))

nhes05v2 = data.frame(AWHITE, ABLACK, AASIAN, AAMIND, APACI)
> nhes05v2  # Partial output given
   AWHITE ABLACK AASIAN AAMIND APACI
1       1      2      2      2     2
2       1      1      2      2     2
3       1      2      2      2     2
...
18      1      2      2      2     2
19      1      2      2      2     2
20      1      2      2      2     2
  

Перекодируйте переменные

 # Recode variables. Change all 2's to 0's (New coding is 1 = Yes, 0 = No).
nhes05v2[nhes05v2 == 2] = 0
  

Создайте 2 функции, удовлетворяющие критериям для ARACE и AORACE

 # A person is mixed race it they answer 1 to more than one race
# Therefore a person whose row sum is greater than 1 is mixed race

determine.arace = function(AWHITE, ABLACK, AAMIND, AASIAN, APACI){
  ifelse( sum(AWHITE, ABLACK, AAMIND, AASIAN, APACI ) > 1 , 91, 0)
}

determine.aothrace = function(AWHITE, ABLACK, AAMIND, AASIAN, APACI){
  ifelse( sum(AWHITE, ABLACK, AAMIND, AASIAN, APACI ) > 1 , 2, 0)
}
  

Примените эти функции к своим данным

 ARACE = mapply(determine.arace, nhes05v2$AWHITE, nhes05v2$ABLACK, nhes05v2$AAMIND, nhes05v2$AASIAN, nhes05v2$APACI)
> ARACE
[1]  0 91  0 91  0 91 91  0  0  0  0  0  0 91  0  0  0  0  0  0

AOTHRACE = mapply(determine.aothrace, nhes05v2$AWHITE, nhes05v2$ABLACK, nhes05v2$AAMIND, nhes05v2$AASIAN, nhes05v2$APACI)
> AOTHRACE
[1] 0 2 0 2 0 2 2 0 0 0 0 0 0 2 0 0 0 0 0 0
  

Чтобы добавить их в ваш фрейм данных

 nhes05v2$ARACE = ARACE
nhes05v2$AOTHRACE = AOTHRACE
  

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

1. Большое вам спасибо! Это легко приводит меня к тому, что мне нужно для всего этого дополнительного кода! И спасибо вам за ваши комментарии, которые помогут прояснить мой вопрос.

2. @jazlaw, рад это слышать! Удачи в ваших исследованиях 🙂

Ответ №2:

Используя пакеты dplyr и magrittr , моя лучшая версия этого выглядит следующим образом:

 nhes05v2 %>%
  mutate(ARACE = ifelse(AWHITE == 1 amp; (ABLACK == 1 | AAMIND ==1 | AASIAN == 1 | APACI == 1), 91, 0),
         AOTHRACE = ifelse(AWHITE == 1 amp; (ABLACK == 1 | AAMIND ==1 | AASIAN == 1 | APACI == 1), 2, 0))
  

Условие amp;amp; в R проверяет только первую строку, вот почему вы получили результаты, которые вы сделали здесь — вот сообщение от других людей, которые были сбиты с толку таким поведением.