R - 如何创建重复的自定义 Ifelse 函数

Nat*_*son 5 if-statement r

我非常熟悉 R 的标准 ifelse 语句,以及如何创建嵌套的 ifelse 语句。但是,我想创建一个“更好”的版本,这样我就不必多次复制/粘贴 ifelse。

以这个嵌套的 ifelse 语句为例:

df <- data.frame(b = 1:5)

df$a <- ifelse(df$b == 1,1,
        ifelse(df$b == 2,2,
        ifelse(df$b == 3,3,4)))
Run Code Online (Sandbox Code Playgroud)

相反,我想做的是创建一个函数,就像我可以这样调用:

df$a <- myFunction(df$b == 1,1,
                   df$b == 2,2,
                   df$b == 3,3,4)
Run Code Online (Sandbox Code Playgroud)

我希望该函数能够获取我输入的参数数量,从而知道要包含多少 ifelse 语句,然后将参数插入正确的位置,直到我想要的数量为止。

仍然有一些重复,但是在创建更长的嵌套 ifelse 语句时,最好不必重复那段代码,然后尝试跟踪结束括号的。

bgo*_*dst 5

我们可以使用Reduce()来构建所需的嵌套ifelse()调用解析树,然后eval():

ifelses <- function(...) {
    ## validate number of args is at least 3 and odd
    stopifnot(nargs()>=3L);
    stopifnot(nargs()%%2L==1L);
    ## precompute the required number of calls and the argument parse tree list
    num <- (nargs()-1L)%/%2L;
    cl <- match.call();
    ## build up the parse tree of nested ifelse() calls using Reduce(), then eval() it
    ## terminology (following docs): ifelse(test,yes,no)
    eval(Reduce(
        function(i,noArg) call('ifelse',cl[[i]],cl[[i+1L]],noArg),
        seq(2L,by=2L,len=num), ## indexes of "test" args
        cl[[length(cl)]], ## first (innermost) "no" arg
        T ## proceed from right-to-left, IOW inside-out wrt parse tree
    ));
}; ## end ifelses()
Run Code Online (Sandbox Code Playgroud)

有用的文档:

演示:

ifelses(c(F,T,F,F),1:4,c(T,F,F,F),5:8,c(F,T,F,T),9:12,13:16);
## [1]  5  2 15 12
Run Code Online (Sandbox Code Playgroud)

OP的例子:

df <- data.frame(b=1:5);
df$a <- ifelses(df$b==1L,1L,df$b==2L,2L,df$b==3L,3L,4L);
df;
##   b a
## 1 1 1
## 2 2 2
## 3 3 3
## 4 4 4
## 5 5 4
Run Code Online (Sandbox Code Playgroud)