我非常熟悉 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)))
相反,我想做的是创建一个函数,就像我可以这样调用:
df$a <- myFunction(df$b == 1,1,
df$b == 2,2,
df$b == 3,3,4)
我希望该函数能够获取我输入的参数数量,从而知道要包含多少 ifelse 语句,然后将参数插入正确的位置,直到我想要的数量为止。
仍然有一些重复,但是在创建更长的嵌套 ifelse 语句时,最好不必重复那段代码,然后尝试跟踪结束括号的。
最佳答案
我们可以使用 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()
有用的文档:
nargs()
stopifnot()
match.call()
Reduce()
call()
eval()
seq()
ifelse()
演示:
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
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
关于R - 如何创建重复的自定义 Ifelse 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39174101/