使用调用更新 "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)
接下来,一个做岭回归的函数。它是 X
、y
和脊线惩罚 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_X
和 preset_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()
的信息,隐含地。 ..)
我在理解如何在 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)
接下来,一个做岭回归的函数。它是 X
、y
和脊线惩罚 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_X
和 preset_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()
的信息,隐含地。 ..)