在转换中使用switch语句

时间:2014-12-12 13:52:14

标签: r switch-statement

我有一个数据框:

    Exposure Signal  Noise ill ADC
201     0.01  185.0 0.6744   1  12
471     0.03  210.2 0.7683   4  12
101     0.01  218.2 0.8356   1  10
381     0.03  249.5 0.8609   4  10
1       0.01  258.4 0.8988   1   9
301     0.03  292.7 0.8326   4   9

我希望将Exposure乘以一个因子,具体取决于ill值,后者可以是1,4或10。

我尝试了以下内容:

df2 <- transform(df, Exposure = Exposure * switch ("ill", "1"=1, "4"=3, "10"=11.5)  )

但我得到的只是df2$Exposure中的NAs 我做错了什么?

4 个答案:

答案 0 :(得分:3)

switch在这里不是正确的事情 - 你需要为ill的所有值进行矢量化的东西。你所得到的是对角色价值的影响&#34;生病&#34; - 它根本没有看你的数据框架!

这方面的线索包括:

> switch ("ill", "1"=1, "4"=3, "10"=11.5)
> 

什么都不返回......

> switch (df$ill, "1"=1, "4"=3, "10"=11.5)
Error in switch(df$ill, `1` = 1, `4` = 3, `10` = 11.5) : 
  EXPR must be a length 1 vector

错误,因为你给它喂了一个矢量。

我为你的乘法创建了一个查找表:

> map=data.frame(ill=c(1,4,10), factor=c(1,3,11.5))
> map
  ill factor
1   1    1.0
2   4    3.0
3  10   11.5

然后使用dplyr内部联接来获取每行的因子:

> require(dplyr)
> df %>% inner_join(map)
Joining by: "ill"
    Exposure ill factor
1  0.3698771   4    3.0
2  0.4274825   4    3.0
3  0.4120654   1    1.0
4  0.3098392   4    3.0
5  0.3205585   4    3.0
6  0.5340227  10   11.5
7  0.6466888  10   11.5
8  0.1581114  10   11.5
9  0.2598404   1    1.0
10 0.3056725   4    3.0

然后添加一个mutate和一个select来取回你想要的东西:

> df %>% inner_join(map) %>% mutate(Exposure=Exposure*factor) %>% select(-factor)
Joining by: "ill"
    Exposure ill
1  1.1096313   4
2  1.2824476   4
3  0.4120654   1
4  0.9295175   4
5  0.9616755   4
6  6.1412607  10
7  7.4369216  10
8  1.8182816  10
9  0.2598404   1
10 0.9170176   4

答案 1 :(得分:2)

如上所述,switch没有矢量化,另一种选择是使用ifelse(即使编写嵌套的ifelse也不是很简单):

df2 <- transform(df, 
        Exposure = Exposure * ifelse(ill== 1,1,
                                     ifelse(ill==4,3,
                                            ifelse(ill==10,11.5,1))))

编辑添加矢量化开关功能

这是首次尝试创建“矢量化开关”功能(该代码仅在OP情况下进行测试):

switch_v <-
  function(expr,...){
    cond <- list(...)
    lefts <- as.numeric(names(cond))
    values <- cond
    for(i in seq_along(lefts))
       expr[expr==lefts[i]] <- values[i]
    unlist(expr)
  }

现在您可以正常使用它switch

df <- transform(df, 
                 Exposure2 = Exposure * switch_v(ill,"1"=1, "4"=3, "10"=11.5))

答案 2 :(得分:1)

您不需要switchifelse

transform(df, Exposure = Exposure * c(1, 3, 11.5)[ill / 4 + 1])

它如何运作?

如果ill / 4 + 1,则1.25会返回ill == 12.0会返回ill == 43.5会返回ill == 10。 这些值用于索引([])。因此,它们会自动转换为整数,即123。这些索引用于从向量c(1, 3, 11.5)中选择适当的值。

答案 3 :(得分:0)

我认为最简单的方法是使用sapply

df2 <- transform (df, Exposure = Exposure * sapply(as.character(ill), switch, "1" = 1, "4"=3, "10" = 11.5))