Использование переключателя() в R для замены векторных значений
Это должно быть довольно простым, но даже после проверки всех документов и онлайновых примеров я не понимаю.
Я хотел бы использовать switch() для замены значений символьного вектора.
Поддельный, чрезвычайно простой, воспроизводимый пример:
test<-c("He is", "She has", "He has", "She is")
Скажем, я хочу назначить "1" предложениям, включая глагол "быть" и "2", к предложениям, включая глагол "иметь". Следующие НЕ РАБОТАЮТ:
test<-switch(test,
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2)
Сообщение об ошибке:
+ + + + Error in switch(test, `He is` = 1, `She is` = 1, `He has` = 2, `She has` = 2) :
EXPR must be a length 1 vector
Я думаю, что EXPR действительно является вектором длины 1, так что неправильно?
Я подумал, что, возможно, ожидаемые символы R были заменены, но ни один из переключателей wrap() в "as.integer" и следующую работу:
test<-switch(test,
"He is"="1",
"She is"="1",
"He has"="2",
"She has"="2")
Может, это не векторизация, и я должен сделать цикл? Это оно? Было бы неутешительно, учитывая, что сила R - векторизация. Спасибо заранее!
Ответы
Ответ 1
Вектор вектора if
равен ifelse
:
test <- ifelse(test == "He is", 1,
ifelse(test == "She is", 1,
ifelse(test == "He has", 2,
2)))
или
test <- ifelse(test %in% c("He is", "She is"), 1, 2)
switch
- это в основном способ записи вложенных тестов if
- else
. Вы должны думать о if
и switch
как инструкции потока управления, а не как операторы преобразования данных. Вы используете их для управления выполнением алгоритма, например, для проверки конвергенции или выбора пути выполнения. Вы не использовали бы их для непосредственного управления данными в большинстве случаев.
Ответ 2
Вот правильный способ векторизации функции, например, switch:
# Data vector:
test <- c("He is",
"She has",
"He has",
"She is")
# Vectorized SWITCH:
foo <- Vectorize(vectorize.args = "a",
FUN = function(a) {
switch(as.character(a),
"He is" = 1,
"She is" = 1,
"He has" = 2,
2)})
# Result:
foo(a = test)
He is She has He has She is
1 2 2 1
Надеюсь, это поможет.
Ответ 3
Вы можете попробовать
test_out <- sapply(seq_along(test), function(x) switch(test[x],
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2))
Или эквивалентно
test_out <- sapply(test, switch,
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2)
Ответ 4
Я нашел этот подход наиболее читаемым:
# input
test <-c("He is", "She has", "He has", "She is", "Unknown", "She is")
# mapping
map <- c(
"He is" = 1,
"She has" = 2,
"He has" = 2,
"She is" = 1)
answer <- map[test]
# output
answer
He is She has He has She is <NA> She is
1 2 2 1 NA 1
Если test
является числовым, необходимо преобразовать значение в character
, чтобы использовать это.
Ответ 5
Хотя я обычно предпочитаю базовые подходы R, есть пакет с векторной функцией переключения.
library(broman)
switchv(c("horse", "fish", "cat", "bug"),
horse="fast",
cat="cute",
"what?")
Добавлено на основе комментария для использования данных OP.
library(broman)
test<-c("He is", "She has", "He has", "She is")
test<-switchv(test,
"He is"="1",
"She is"="1",
"He has"="2",
"She has"="2")
test
Ответ 6
"Веклизатор" основан на функции "mapply", тогда как "ifelse" - это базовая функция, которая должна быть уже векторизована. Так что с точки зрения производительности "Vectorize" может быть медленнее.
Легко векторизовать R-функцию с семейством "apply", но производительность обычно является проблемой на больших томах. Лучше использовать базовые функции, оптимизированные для работы с векторами.
Ответ 7
Вот решение с recode()
от car
:
# Data vector:
x <- c("He is", "She has", "He has", "She is")
library("car")
recode(x, "'He is'=1; 'She is'=1; 'He has'=2; 'She has'=2") # or
recode(x, "c('He is', 'She is')=1; c('He has', 'She has')=2")
Ответ 8
Возможно, попробуйте следующее:
test<-c("He is", "She has", "He has", "She is")
numbers <-c(1,2,2,1)
test<-mapply(switch, as.list(test), as.list(numbers))