2016-12-13 85 views
0

我在理解如何在R中使用调用时遇到了一些问题。我想获取由函数创建的对象并将其用作另一个函数的参数,沿途修改原始函数的一些参数。我看过Hadley Wickham's page on expressions,,但它似乎并没有告诉我如何去做我想做的事情。使用调用来更新函数中的“调用”R

这是我想要做的事情的一个部分工作的例子。首先,假数据:

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的函数。它返回系数和呼叫:

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) 
+0

所以,这个调用是'pols(X = X,y = y,L = 1)'。采取这些论点,以便他们可以在第二步中修改。所以就像使'L <-2' –

+0

这只是一个虚拟的例子。我的真实代码要复杂得多。基本上我有一个很长的参数列表,我只想修改其中的一个。我必须循环'pols(q,w,e,r,t,y,u ,, o,p,a,s,d,f,g,i)' –

回答

2

我要在这里做一些猜测/假设。 (1)当你说“一个pols对象”时,你的意思是由pols函数返回的一个对象。我在下面修改了pols(),以便返回“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()的信息,隐含...)

+0

有趣。你没有使用'match.call'中的信息。我想我的先前是,拯救电话的全部目的是进行各种更新。 –

0
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) 
+0

'X'和'y'一定不会在全球环境中。 –

+0

@generic_user您可以在此情况下设置或预先设置环境。这里有一个例子:http://adv-r.had.co.nz/Environments.html –

+0

我真正想要做的是找到避免重新指定大量参数列表的方法。 –

1

如果我猜得不错,以你需要什么,我会用partialpryr包。这使您可以创建一个函数与一些已经设定的参数:

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) 
+0

这很好,谢谢。但我很惊讶,在R中没有解决方案。如果不是为了保存参数以供稍后重新评估,'match.call()'有什么意义? –

+0

你可以使用'do.call'来运行带有参数列表的函数。只需使用带有预设参数的列表并追加'L = 1'即可。 –