2016-12-13 33 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'即可。 –