2016-02-11 207 views
6

当我不得不链ifelse语句,它看起来像:聪明的方式链ifelse语句?

ifelse(input=="x","x1", 
     ifelse(input=="y","x2", 
       ifelse(input=="z","x3",NA))) 

有没有一种更聪明的办法做到这一点?我正在考虑创建表格然后合并或者只是为了使代码看起来更好?

+3

使用一个已命名的向量或列表,或查看'switch'或'factor'。 – A5C1D2H2I1M1N2O1R2T1

+0

我发现多个ifelse链更具可读性如果您不缩进每个新的ifelse,而是在',NA)))'之前添加换行符, – Pekka

+0

我会建议使用表格,但最简单的'ifelse'语句。使得它更容易调试,并在未来明白。 – Hugh

回答

11
从建议

除了在注释中,你也可以通过以下方式使用match

创建示例数据:

set.seed(1) 
vals_in <- c("x", "y", "z") # unique values in your input vector 
vec_in <- sample(vals_in, 10, replace = TRUE) # sample from vals_in to create input 
vals_out <- c("x1", "x2", "x3") # values to replace 

现在,替换的嵌套ifelse是你可以做:

vec_out <- vals_out[match(vec_in, vals_in)] 

结果是

vec_out 
# [1] "x1" "x2" "x2" "x3" "x1" "x3" "x3" "x2" "x2" "x1" 

一点比较两种方法:

set.seed(1) 
vals_in <- letters 
vec_in <- sample(vals_in, 1e7, replace = TRUE) 
vals_out <- LETTERS 

system.time(vals_out[match(vec_in, vals_in)]) 
     User  System verstrichen 
     0.378  0.020  0.398 
system.time(unname(setNames(vals_out, vals_in)[vec_in])) 
     User  System verstrichen 
     1.020  0.062  1.084 
+0

这很酷。但任何建议如何处理其他类型的条件,如不平等? – Pekka

+0

@Pekka,一个小例子将是很好的测试它。你有没有想过? –

+0

嗯,我在想这样的事情:'x = 1:14; (x = 5,'a', ifelse(x%in%c(1,4),'b', ifelse(x≤10,'c', ifelse(x≤12, 'd', 'e'))))' – Pekka

8

你可以尝试这样的函数之一:

choice <- function(input) { 
    switch(input, 
     "x"="x1", 
     "y"="x2", 
     "z"="x3", 
     NA) 
} 
#> choice("x") 
#[1] "x1" 
#> choice("z") 
#[1] "x3" 
#> choice("other") 
#[1] NA 
+0

@docendodiscimus可以把这个函数包装成'sapply()'来处理一个输入向量,像这样:'sapply(my_vector,choice)',但是我认为这不会产生非常快的性能。 – RHertel

5

另一种办法是使用setNames

unname(setNames(vals_out, vals_in)[vec_in]) 
#[1] "x1" "x2" "x2" "x3" "x1" "x3" "x3" "x2" "x2" "x1" 

注:摘自@docendo discimus后的例子。