使用调用更新 "calls" 到 R 中的函数

Using calls to update "calls" to functions in R

我在理解如何在 R 中使用调用时遇到了一些麻烦。我想获取一个函数创建的对象并将其用作另一个函数的参数,修改原始函数的一些参数一路上。我看过 Hadley Wickham's page on expressions,,但它似乎并没有告诉我如何做我想做的事。

这是我想做的事情的部分工作示例。一、假数据:

library(MASS)
N <- 1000
p <- 10
A <- matrix(rnorm(p^2), p)
X <- mvrnorm(N, rep(0, p), t(A) %*% A)
B <- rnorm(p)
y <- X %*% B + rnorm(N)

接下来,一个做岭回归的函数。它是 Xy 和脊线惩罚 L 的函数。它 returns 系数和调用:

pols <- function(X, y, L){
  cl <- match.call()
  beta <- solve(t(X) %*% X + diag(rep(L, p))) %*% t(X) %*% y
  return(list(beta = beta, cl = cl))
}

1> pols(X, y, 1)
$beta
             [,1]
 [1,] -0.02622669
 [2,] -1.96523722
 [3,]  0.36375563
 [4,] -1.14192468
 [5,] -0.14436051
 [6,] -0.29700918
 [7,] -0.81543748
 [8,] -0.17699934
 [9,] -0.01342649
[10,]  0.58862577

$cl
pols(X = X, y = y, L = 1)

现在,我该如何使用调用来驱动下面的函数呢?它需要一个 pols 对象和一个 L 不同值的向量,并使用它们重新调用 pols

Lvec <- 1:10    
tryLs <- function(pols, Lvec){
      for (i in Lvec){
        1.  Extract the args from the call in pols
        2.  Modify the argument `L` based on Lvec
        3.  Run `pols` with old arguments, but `L` modified according to `i`
      }
    }

如何使最后一个功能起作用?

澄清一下,我设想的工作流程类似于:

obj <- pols(X, y, 0)
Lvec <- 1:10
output <- tryLs(obj, Lvec)
Lvec <- 1:10    
tryLs <- function(pols, Lvec){
  for (i in Lvec){
    print(paste("Result for ",i))
    print(pols(X,y,i))$beta
    print(pols(X,y,i))$cl

  }
}

tryLs(pols,Lvec)
[1] "Result for  1"
$beta
             [,1]
 [1,]  0.03317113
 [2,] -0.37399461
 [3,] -1.35395755
 [4,]  0.09850883
 [5,] -0.14503628
 [6,] -1.97204600
 [7,] -0.56459244
 [8,] -1.10422047
 [9,] -0.92047748
[10,]  1.76236287

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,]  0.03317113
 [2,] -0.37399461
 [3,] -1.35395755
 [4,]  0.09850883
 [5,] -0.14503628
 [6,] -1.97204600
 [7,] -0.56459244
 [8,] -1.10422047
 [9,] -0.92047748
[10,]  1.76236287

$cl
pols(X = X, y = y, L = i)

[1] "Result for  2"
$beta
             [,1]
 [1,] -0.01014376
 [2,] -0.32064189
 [3,] -1.29381243
 [4,]  0.10695047
 [5,] -0.24791384
 [6,] -1.83662948
 [7,] -0.55615073
 [8,] -1.12204424
 [9,] -0.96717380
[10,]  1.79084625

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,] -0.01014376
 [2,] -0.32064189
 [3,] -1.29381243
 [4,]  0.10695047
 [5,] -0.24791384
 [6,] -1.83662948
 [7,] -0.55615073
 [8,] -1.12204424
 [9,] -0.96717380
[10,]  1.79084625

$cl
pols(X = X, y = y, L = i)

[1] "Result for  3"
$beta
             [,1]
 [1,] -0.04097765
 [2,] -0.28237279
 [3,] -1.25064282
 [4,]  0.11286963
 [5,] -0.32135783
 [6,] -1.74000917
 [7,] -0.55025764
 [8,] -1.13481390
 [9,] -1.00038377
[10,]  1.81099139

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,] -0.04097765
 [2,] -0.28237279
 [3,] -1.25064282
 [4,]  0.11286963
 [5,] -0.32135783
 [6,] -1.74000917
 [7,] -0.55025764
 [8,] -1.13481390
 [9,] -1.00038377
[10,]  1.81099139

$cl
pols(X = X, y = y, L = i)

[1] "Result for  4"
$beta
             [,1]
 [1,] -0.06401718
 [2,] -0.25352501
 [3,] -1.21807596
 [4,]  0.11721395
 [5,] -0.37641945
 [6,] -1.66761823
 [7,] -0.54595545
 [8,] -1.14442668
 [9,] -1.02517135
[10,]  1.82592968

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,] -0.06401718
 [2,] -0.25352501
 [3,] -1.21807596
 [4,]  0.11721395
 [5,] -0.37641945
 [6,] -1.66761823
 [7,] -0.54595545
 [8,] -1.14442668
 [9,] -1.02517135
[10,]  1.82592968

$cl
pols(X = X, y = y, L = i)

[1] "Result for  5"
$beta
             [,1]
 [1,] -0.08186374
 [2,] -0.23095555
 [3,] -1.19257456
 [4,]  0.12050945
 [5,] -0.41923287
 [6,] -1.61137106
 [7,] -0.54271257
 [8,] -1.15193566
 [9,] -1.04434740
[10,]  1.83739926

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,] -0.08186374
 [2,] -0.23095555
 [3,] -1.19257456
 [4,]  0.12050945
 [5,] -0.41923287
 [6,] -1.61137106
 [7,] -0.54271257
 [8,] -1.15193566
 [9,] -1.04434740
[10,]  1.83739926

$cl
pols(X = X, y = y, L = i)

[1] "Result for  6"
$beta
             [,1]
 [1,] -0.09607715
 [2,] -0.21277987
 [3,] -1.17201761
 [4,]  0.12307151
 [5,] -0.45347618
 [6,] -1.56641949
 [7,] -0.54021027
 [8,] -1.15797228
 [9,] -1.05959733
[10,]  1.84644233

$cl
pols(X = X, y = y, L = i)

$beta
             [,1]
 [1,] -0.09607715
 [2,] -0.21277987
 [3,] -1.17201761
 [4,]  0.12307151
 [5,] -0.45347618
 [6,] -1.56641949
 [7,] -0.54021027
 [8,] -1.15797228
 [9,] -1.05959733
[10,]  1.84644233

$cl
pols(X = X, y = y, L = i)

[1] "Result for  7"
$beta
            [,1]
 [1,] -0.1076495
 [2,] -0.1977993
 [3,] -1.1550561
 [4,]  0.1251007
 [5,] -0.4814888
 [6,] -1.5296799
 [7,] -0.5382458
 [8,] -1.1629381
 [9,] -1.0719931
[10,]  1.8537217

$cl
pols(X = X, y = y, L = i)

$beta
            [,1]
 [1,] -0.1076495
 [2,] -0.1977993
 [3,] -1.1550561
 [4,]  0.1251007
 [5,] -0.4814888
 [6,] -1.5296799
 [7,] -0.5382458
 [8,] -1.1629381
 [9,] -1.0719931
[10,]  1.8537217

$cl
pols(X = X, y = y, L = i)

[1] "Result for  8"
$beta
            [,1]
 [1,] -0.1172419
 [2,] -0.1852151
 [3,] -1.1407910
 [4,]  0.1267308
 [5,] -0.5048296
 [6,] -1.4990974
 [7,] -0.5366841
 [8,] -1.1671009
 [9,] -1.0822491
[10,]  1.8596792

$cl
pols(X = X, y = y, L = i)

$beta
            [,1]
 [1,] -0.1172419
 [2,] -0.1852151
 [3,] -1.1407910
 [4,]  0.1267308
 [5,] -0.5048296
 [6,] -1.4990974
 [7,] -0.5366841
 [8,] -1.1671009
 [9,] -1.0822491
[10,]  1.8596792

$cl
pols(X = X, y = y, L = i)

[1] "Result for  9"
$beta
            [,1]
 [1,] -0.1253119
 [2,] -0.1744744
 [3,] -1.1286001
 [4,]  0.1280542
 [5,] -0.5245776
 [6,] -1.4732498
 [7,] -0.5354316
 [8,] -1.1706458
 [9,] -1.0908596
[10,]  1.8646205

$cl
pols(X = X, y = y, L = i)

$beta
            [,1]
 [1,] -0.1253119
 [2,] -0.1744744
 [3,] -1.1286001
 [4,]  0.1280542
 [5,] -0.5245776
 [6,] -1.4732498
 [7,] -0.5354316
 [8,] -1.1706458
 [9,] -1.0908596
[10,]  1.8646205

$cl
pols(X = X, y = y, L = i)

[1] "Result for  10"
$beta
            [,1]
 [1,] -0.1321862
 [2,] -0.1651825
 [3,] -1.1180392
 [4,]  0.1291370
 [5,] -0.5415033
 [6,] -1.4511217
 [7,] -0.5344217
 [8,] -1.1737051
 [9,] -1.0981778
[10,]  1.8687639

$cl
pols(X = X, y = y, L = i)

$beta
            [,1]
 [1,] -0.1321862
 [2,] -0.1651825
 [3,] -1.1180392
 [4,]  0.1291370
 [5,] -0.5415033
 [6,] -1.4511217
 [7,] -0.5344217
 [8,] -1.1737051
 [9,] -1.0981778
[10,]  1.8687639

$cl
pols(X = X, y = y, L = i)

如果我猜对了您的需求,我会使用 pryr 包中的 partial。这允许您创建一个函数,其中已经设置了一些参数:

library(pryr)
preset_pols = partial(pols, X = preset_X, y = preset_y)
preset_pols(L = 1)

调用 preset_pols 现在将始终使用 preset_Xpreset_y 中指定的数据。

在我看来没有必要 for 循环,lapply 在这里就可以了:

list_of_results = lapply(Lvec, preset_pols)

我要在这里做一些guesses/assumptions。

(1) 当您说 "a pols object" 时,您指的是 pols 函数返回的对象。我修改了下面的 pols(),使其 returns 成为 "pols" 类型的对象。这根本不是必需的,但如果您想做更奇特的事情(例如,为这些对象实施自定义打印或绘图方法),将来可能会有用。

设置:

library(MASS)
N <- 1000
p <- 10
A <- matrix(rnorm(p^2), p)
X <- mvrnorm(N, rep(0, p), t(A) %*% A)
B <- rnorm(p)
y <- X %*% B + rnorm(N)

我也在修改 pols 以便调用包含调用的元素 call:这使得对象自动使用 R 的默认 update 方法。

pols <- function(X, y, L){
   cl <- match.call()
   beta <- solve(t(X) %*% X + diag(rep(L, p))) %*% t(X) %*% y
   r <- list(beta = beta, call = cl)
   class(r) <- "pols"
   return(r)
}

为了得到一个 pols 对象,我们必须 运行 pols() 一次并保存结果:

pols1 <- pols(X,y,0)

现在是你的函数。我的第二个假设是您只希望返回 $beta 值 ...

tryLs <- function(pols,Lvec) {
    sapply(Lvec,
           function(L) update(pols,L=L)$beta)
}
Lvec <- 1:10
tryLs(pols1,Lvec)

如果你想在更具体的层面上做到这一点(而不是使用 update),你可以按照

的方式做一些事情
pols$call$L <- new_L_value
new_result <- eval(pols$call,parent.frame())

如果您查看 update.default(),您或多或少会发现它的作用(它 使用来自 match.call() 的信息,隐含地。 ..)