Использование switch () в 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 ожидал символов в качестве замены, но ни обертывание switch() в "as.integer " или следующая работа:
test<-switch(test,
"He is"="1",
"She is"="1",
"He has"="2",
"She has"="2")
может быть, он не векторизуется, и я должен сделать цикл? Это все? Было бы разочаровывающе, учитывая силу R-векторизации. Заранее спасибо!
7 ответов
векторизованная форма 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
as поток управления операторы, а не операторы преобразования данных. Они используются для управления выполнением алгоритма, например для проверки сходимости или выбора пути выполнения. Вы не будете использовать их для прямого управления данными в большинстве обстоятельства.
вот это правильно векторизовать функция, например,переключатель:
# Data vector:
test<-c("He is", "She has", "He has", "She is")
# Vectorized SWITCH:
foo <- Vectorize(function(a) {
switch(as.character(a),
"He is" = 1,
"She is" = 1,
"He has" = 2,
2)
}, "a")
# Result:
foo(test)
He is She has He has She is
1 2 2 1
надеюсь, это поможет.
вы могли бы попробовать
test_out <- sapply(1:length(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)
" векторизация "основана на функции" mapply", тогда как" ifelse " является базовой функцией, которая должна быть уже векторизована. Поэтому с точки зрения производительности "векторизация" может быть медленнее. Легко векторизовать функцию R с семейством "apply", но производительность обычно является проблемой на больших объемах. Лучше использовать базовые функции, оптимизированные для работы с векторами.
Я нашел этот подход наиболее читаемым:
# 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
чтобы использовать это.
хотя я обычно предпочитаю базовые подходы R, есть пакет с векторизованной функцией переключения.
library(broman)
switchv(c("horse", "fish", "cat", "bug"),
horse="fast",
cat="cute",
"what?")
может попробовать так:
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))