Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 在Lappy中将函数作为参数传递给FUN_R_Non Standard Evaluation - Fatal编程技术网

R 在Lappy中将函数作为参数传递给FUN

R 在Lappy中将函数作为参数传递给FUN,r,non-standard-evaluation,R,Non Standard Evaluation,我正在设计一个适合模型的包,该模型涉及矩阵列的基展开。我希望扩展是用户定义的,这样任何扩展都是可能的,例如spline::bs,spline::ns,stats::poly。相同的展开式应用于矩阵的每一列。我尝试了eval和substitute的一些组合,但无法使其在嵌套函数中工作 我想做的事 set.seed(123) (材料[,1][,2][,3][,4] #> [1,] -0.56047565 1.2240818 -1.0678237 0.42646422 #> [2,] -0.

我正在设计一个适合模型的包,该模型涉及矩阵列的基展开。我希望扩展是用户定义的,这样任何扩展都是可能的,例如
spline::bs
spline::ns
stats::poly
。相同的展开式应用于矩阵的每一列。我尝试了
eval
substitute
的一些组合,但无法使其在嵌套函数中工作

我想做的事

set.seed(123)
(材料[,1][,2][,3][,4]
#>  [1,] -0.56047565  1.2240818 -1.0678237  0.42646422
#>  [2,] -0.23017749  0.3598138 -0.2179749 -0.29507148
#>  [3,]  1.55870831  0.4007715 -1.0260044  0.89512566
#>  [4,]  0.07050839  0.1106827 -0.7288912  0.87813349
#>  [5,]  0.12928774 -0.5558411 -0.6250393  0.82158108
#>  [6,]  1.71506499  1.7869131 -1.6866933  0.68864025
#>  [7,]  0.46091621  0.4978505  0.8377870  0.55391765
#>  [8,] -1.26506123 -1.9666172  0.1533731 -0.06191171
#>  [9,] -0.68685285  0.7013559 -1.1381369 -0.30596266
#> [10,] -0.44566197 -0.4727914  1.2538149 -0.38047100

fitOoh,你很接近了。你只需要把表达式变成一个函数

fit <- function(x, expr = function(i) splines::bs(i, df = 5)) {
  nvars <- ncol(x)
  x <- scale(x, center = TRUE, scale = FALSE)
  design <- design_mat(x = x, expr = expr, nvars = nvars)
  # then fit some model on design
}

fit这里是另一个使用非标准求值来更改调用的解决方案
spline::bs(x,df=6)
。其基本思想依赖于使用
rlang
包来更改从用户捕获的抽象语法树。下面是解决方案;详细信息如下所示:

fit <- function(expr = splines::bs(x, df = 6)) {
    sexpr <- rlang::enexpr(expr)
    new_expr <- call2(sexpr[[1]],
                      call2(`[`, sexpr[[2]],
                            call2(seq_len,
                                  call2(nrow, 
                                        sexpr[[2]])), 
                            sym("i")),
                      splice(as.list(sexpr)[-c(1:2)]))

    seq_col <- call2(seq_len, call2(ncol, sexpr[[2]]))
    design <- lapply(eval(seq_col), function(i) eval(new_expr))

    # then fit some model on design
}
3.创建
spline::bs(x[,i],df=6)
这很棘手,因为我们需要跟踪额外的参数。为此,我们可以使用函数
rlang::splice
。如果让
foo
作为上面步骤2中创建的表达式,我们可以编写

`call2(sexpr[[1]], foo, splice(as.list(sexpr)[-c(1:2)]))`
请注意,我们从
sexpr
中删除了第一个和第二个插槽,它们分别对应于函数和矩阵
x

4.创建
seq_len(ncol(x))
我们现在在这方面做得很好:
call2(seq_len,call2(ncol,sexpr[[2]])

5.将所有内容放在一起并进行评估
这是最后一行
lappy(eval(seq_col),function(i)eval(new_expr))

我认为其目的是以编程方式(用
sexpr[[2]]替换
i
,这几乎像一个占位符。类似于曲线(f(i),xname=“i”).r2evans是的,你是对的。这就是M Turgeon的答案,但要小心:
splice()处于提问阶段。不清楚是否真的需要它,因为有其他方法可以避免上面部分讨论的性能问题。
(来自帮助页)
`call2(sexpr[[1]], foo, splice(as.list(sexpr)[-c(1:2)]))`