在R中使用switch()来替换矢量值

问题描述 投票:18回答:7

这应该是非常简单的,但即使在检查了所有文档和在线示例后,我也没有得到它。

我想使用switch()来替换字符向量的值。

一个假的,极其简单,可重复的例子:

test<-c("He is", "She has", "He has", "She is")

假设我想将“1”包括动词“to be”和“2”分配给句子,包括动词“to have”。以下不起作用:

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的强度是矢量化,会令人失望。提前致谢!

r string replace switch-statement
7个回答
12
投票

矢量化形式的ififelse

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测试的方法。您应该将ifswitch视为控制流语句,而不是数据转换运算符。您可以使用它们来控制算法的执行,例如测试收敛或选择要执行的执行路径。在大多数情况下,您不会使用它们直接操作数据。


21
投票

这是矢量化函数的正确方法,例如,开关:

# 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

我希望这有帮助。


11
投票

你可以试试

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)

3
投票

我发现这种方法最具可读性:

# 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才能使用它。


3
投票

虽然我通常更喜欢基本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

2
投票

“Vectorize”基于“mapply”函数,而“ifelse”是应该已经向量化的基函数。因此,在性能方面,“Vectorize”可能会更慢。使用'apply'系列很容易对R函数进行矢量化,但性能通常是大容量的问题。最好使用优化的基本函数来处理向量。


0
投票

这是来自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")
© www.soinside.com 2019 - 2024. All rights reserved.