Ответ 1
Исходный метод назначения не работает по крайней мере по двум причинам.
1) Проблема с индексированным присваиванием df$major[df$degree1 == "BA"] <-
. Использование ==
может вызвать NA
, что и вызвало ошибку. From ?"[<-"
: "При замене (с использованием индексации на lhs присваивания) NA не выбирает какой-либо элемент для замены. Поскольку существует двусмысленность относительно того, должен ли использоваться элемент rhs или нет, это разрешено только в том случае, если значение rhs имеет длину 1 (поэтому две интерпретации будут иметь одинаковый результат)". Есть много способов обойти это, но я предпочитаю использовать which
:
df$major[which(df$degree1 == "BA")] <-
Отличие состоит в том, что ==
возвращает TRUE
, FALSE
и NA
, а which
возвращает индексы объекта, которые имеют значение TRUE
> df$degree1 == "BA"
[1] FALSE NA TRUE TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> which(df$degree1 == "BA")
[1] 3 4 5 8 9 10 11 12 13 14 15 16 17 18 19 20
2) Когда вы выполняете индексированное присваивание, правая сторона должна сместиться в левую сторону разумно (так я думаю об этом). Это может означать левую и правую стороны равной длины, что, по-вашему, означает ваш пример. Следовательно, вам нужно будет также подмножать правую часть задания:
df$major[which(df$degree1 == "BA")] <- df$subj1[which(df$degree1 == "BA")]
Я надеюсь, что это разъяснит, почему ваша первоначальная попытка вызвала ошибку.
Использование ifelse
, как предложено @DavidRobinson, является хорошим способом выполнения этого типа назначения. Я беру на себя это:
df$major2 <- ifelse(df$degree1 == "BA", df$subj1, ifelse(df$degree2 == "BA",
df$subj2,NA))
Это эквивалентно
df$major[which(df$degree1 == "BA")] <- df$subj1[which(df$degree1 == "BA")]
df$major[which(df$degree1 != "BA" & df$degree2 == "BA")] <-
df$subj2[which(df$degree1 != "BA" & df$degree2 == "BA")]
В зависимости от глубины вложенных операторов ifelse
другой подход может быть лучше для ваших реальных данных.
EDIT:
Я собирался написать третью причину неудачного первоначального кода (а именно, что df$major
еще не назначен), но он работает для меня, не делая этого. Это была проблема, которую я помню в прошлом. Какую версию R вы используете? (2.15.0 для меня.) Этот шаг не требуется, если вы используете подход ifelse()
. Ваше решение прекрасно подходит при использовании [
, хотя я бы выбрал
df$major <- NA
Чтобы получить знаковые значения объектов, вместо индекса коэффициента, используйте as.character()
(что для коэффициентов эквивалентно и вызывает levels(x)[x]
):
df$major[which(df$degree1 == "BA")] <- as.character(df$subj1)[which(df$degree1 == "BA")]
df$major[which(df$degree1 != "BA" & df$degree2 == "BA")] <-
as.character(df$subj2)[which(df$degree1 != "BA" & df$degree2 == "BA")]
То же самое для способа ifelse()
:
df$major2 <- ifelse(df$degree1 == "BA", as.character(df$subj1),
ifelse(df$degree2 == "BA", as.character(df$subj2), NA))