Заменить значение в кадре данных на основе условного (`if`) оператора в R
В кадре данных R, закодированном ниже, я хотел бы заменить все времена, когда B
появляется с B
.
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")
это обеспечивает:
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B f
7 C g
8 D h
9 A i
10 B j
11 C k
12 D l
Моя первоначальная попытка состояла в том, чтобы использовать инструкции for
и if
:
for(i in junk$nm) if(i %in% "B") junk$nm <- "b"
но, как я уверен, вы можете видеть, это заменяет ВСЕ значения junk$nm
на B
. Я могу понять, почему это делается, но я не могу заставить его заменять только те случаи мусора $nm, где исходное значение было B
.
Спасибо.
ПРИМЕЧАНИЕ. Мне удалось решить проблему с gsub
, но в интересах обучения R я все еще хотел бы знать, как получить мой оригинальный подход к работе (если это возможно)
Ответы
Ответ 1
Легче преобразовать nm в символы и затем внести изменения:
junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"
EDIT: И если вам действительно нужно поддерживать nm как факторы, добавьте это в конец:
junk$nm <- as.factor(junk$nm)
Ответ 2
другой полезный способ заменить значения
library(plyr)
revalue(junk$nm, c("B"="b"))
Ответ 3
Короткий ответ:
junk$nm[junk$nm %in% "B"] <- "b"
Взгляните на Индексные векторы в R Введение (если вы еще не прочитали).
ИЗМЕНИТЬ. Как замечено в комментариях, это решение работает для символьных векторов, поэтому вы теряете свои данные.
Лучшим способом для фактора является изменение уровня:
levels(junk$nm)[levels(junk$nm)=="B"] <- "b"
Ответ 4
Поскольку данные, которые вы показываете, являются факторами, это немного усложняет ситуацию. @diliop Отвечает на проблему путем преобразования в nm
символьной переменной. Чтобы вернуться к исходным факторам, необходим еще один шаг.
Альтернативой является управление уровнями фактора на месте.
> lev <- with(junk, levels(nm))
> lev[lev == "B"] <- "b"
> junk2 <- within(junk, levels(nm) <- lev)
> junk2
nm val
1 A a
2 b b
3 C c
4 D d
5 A e
6 b f
7 C g
8 D h
9 A i
10 b j
11 C k
12 D l
Это довольно просто, и я часто забываю, что есть функция замены для levels()
.
Изменить: Как отмечено @Seth в комментариях, это можно сделать в однострочном режиме без потери ясности:
within(junk, levels(nm)[levels(nm) == "B"] <- "b")
Ответ 5
Самый простой способ сделать это в одной команде - использовать команду which
, а также не нужно менять факторы на символ, делая это:
junk$nm[which(junk$nm=="B")]<-"b"
Ответ 6
Вы создали переменную фактора в nm
, поэтому вам нужно либо не делать этого, либо добавлять дополнительный уровень к атрибутам фактора. Вы также должны избегать использования <-
в аргументах data.frame()
Вариант 1:
junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"
Вариант 2:
levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk