Использование переключателя() в 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))