2012-09-01 66 views
4

您能否向我解釋爲什麼代碼會抱怨說沒有找到SamdatFunction中的函數R

我想在模型之間切換,所以我聲明瞭一個包含這些特定模型的函數,我只需要將該函數作爲get.f函數中的一個參數調用,其中重採樣將更改每個設計矩陣的結構在模型中。該代碼抱怨找不到Samdat

另外,有沒有一種方法可以使條件語句if(Model == M1())而不必創建另一個參數M來設置if(M==1)

這裏是我的代碼:

dat <- cbind(Y=rnorm(20),rnorm(20),runif(20),rexp(20),rnorm(20),runif(20), rexp(20),rnorm(20),runif(20),rexp(20)) 
nam <- paste("v",1:9,sep="") 
colnames(dat) <- c("Y",nam) 

M1 <- function(){ 
    a1 = cbind(Samdat[,c(2:5,7,9)]) 
    b1 = cbind(Samdat[,c(2:4,6,8,7)]) 
    c1 = b1+a1 
    list(a1=a1,b1=b1,c1=c1)} 

M2 <- function(){ 
    a1= cbind(Samdat[,c(2:5,7,9)])+2 
    b1= cbind(Samdat[,c(2:4,6,8,7)])+2 
    c1 = a1+b1 
    list(a1=a1,b1=b1,c1=c1)} 

M3 <- function(){ 
    a1= cbind(Samdat[,c(2:5,7,9)])+8 
    b1= cbind(Samdat[,c(2:4,6,8,7)])+8 
    c1 = a1+b1 
    list(a1=a1,b1=b1,c1=c1)} 
################################################################# 
get.f <- function(asim,Model,M){ 
    sse <-c() 
    for(i in 1:asim){ 
     set.seed(i) 
     Samdat <- dat[sample(1:nrow(dat),nrow(dat),replace=T),] 
     Y <- Samdat[,1] 
     if(M==1){ 
      a2 <- Model$a1 
      b2 <- Model$b1 
      c2 <- Model$c1 
      s<- a2+b2+c2 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      coff <-Model$cof 
      sse <-c(sse,coff) 
     } 
     else if(M==2){ 
      a2 <- Model$a1 
      b2 <- Model$b1 
      c2 <- Model$c1 
      s<- c2+12 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      coff <-Model$cof 
      sse <-c(sse,coff) 
     } 
     else { 
      a2 <- Model$a1 
      b2 <- Model$b1 
      c2 <- Model$c1 
      s<- c2+a2 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      coff <- Model$cof 
      sse <-c(sse,coff) 
     } 
    } 
    return(sse) 
} 

get.f(10,Model=M1(),M=1) 
get.f(10,Model=M2(),M=2) 
get.f(10,Model=M3(),M=3) 
+3

您能否重新加載您的代碼以查看函數的起始和結束位置?也許這也會幫助你解決你的問題。 –

+0

我用一個空格隔開,你是什麼意思加重 –

+0

我的意思是吉爾伯爲你做的。 –

回答

4

當你調用

get.f(10, Model=M1(), M=1) 

M1功能立即調用。它因爲在M1的正文內部而死亡,因此您正在使用Samdat,後者僅在get.f的正文中定義。

不知何故,您需要撥打M1Samdat被定義。這樣做的一個方法是使M1(功能)的參數get.f,並呼籲從內部get.f功能:

get.f <- function(asim, Model.fun, M) { 
    ... 
    Sambat <- ... 
    Model <- Model.fun() 
    ... 
} 
get.f(10, Model.fun = M1, M=1) 

而且,在一般情況下,它是壞的編程中使用全局變量,即讓你的函數使用在其範圍外定義的變量。相反,建議將函數使用的所有內容作爲輸入參數傳遞。您的代碼中有兩種此類情況:M1M2M3)使用Samdatget.f使用dat。他們應該是你的職能的論據。這是你的代碼的更好的版本。我沒有固定的一切,所以你必須做的多一點得到它的工作:

M1 <- function(sampled.data) { 
    a1 <- sampled.data[, c("v1", "v2", "v3", "v4", "v6", "v8")] 
    b1 <- sampled.data[, c("v1", "v2", "v3", "v5", "v7", "v6")] 
    c1 <- a1 + b1 
    list(a1 = a1, b1 = b1, c1 = c1) 
} 

get.f <- function(dat, asim, Model.fun, offset, M) { 
    sse <- c() 
    for(i in 1:asim){ 
     set.seed(i) 
     Samdat <- dat[sample(1:nrow(dat), nrow(dat), replace = TRUE), ] 
     Y  <- Samdat[, "Y"] 
     Model <- Model.fun(sampled.data = Samdat) 
     a2  <- Model$a1 
     b2  <- Model$b1 
     c2  <- Model$c1  
     s  <- switch(M, a2 + b2 + c2, c2 + 12, c2 + a2) 
     fit <- lm(Y ~ s) 
     cof <- sum(summary(fit)$coef[,1]) 
     coff <- Model$cof  # there is a problem here... 
     sse <- c(sse, coff)  # this is not efficient 
    } 
    return(sse) 
} 

dat <- cbind(Y = rnorm(20), v1 = rnorm(20), v2 = runif(20), v3 = rexp(20), 
          v4 = rnorm(20), v5 = runif(20), v6 = rexp(20), 
          v7 = rnorm(20), v8 = runif(20), v9 = rexp(20)) 

get.f(dat, 10, Model.fun = M1, M = 1) 
即跳出

最後一兩件事:如果s的定義(我收集switch()下有關在Model你用,然後再考慮合併的Models的定義放在一起:添加s到你的M1M2M3功能列表輸出,使s可以只被定義爲s <- Model$s,然後你可以刪除M輸入get.f

9

你可能想看看R scoping rules。特別是,沒有理由期望在函數中定義的變量在其他函數中可見。

您可能會感到困惑,因爲全球環境(即所有功能以外的頂級)是該規則的例外。我不打算進入你的其他問題,但讓我注意到,整個腳本看起來非常混亂 - 即M1M3實質上是一個功能,並且在get.f中複製/粘貼的一團肯定是可怕的。無論你想要做什麼,都可以用一種不太複雜的方式寫出來。

讓我們先來看看M - 爲什麼沒有一個帶參數的函數?包括解決您的範圍問題,這使得兩個參數 -

M <- function(sampleData, offset) { 
    a1 = sampleData[,c(2:5,7,9)] + offset 
    b1 = sampleData[,c(2:4,6,8,7)] + offset 
    c1 = b1+a1 
    list(a1=a1,b1=b1,c1=c1) 
} 

如果你堅持定義的別名,你也可以這樣做

M1 <- function(sampleData) M(sampleData, 0) 
M2 <- function(sampleData) M(sampleData, 2) 
M3 <- function(sampleData) M(sampleData, 8) 

這已經是重複率低,但最好要電腦爲你做重複(DRY!):

offsets <- c(0,2,8) 
Models <- sapply(offsets, FUN=function(offset) function(sampleData) M(sampleData, offset)) 

看着get.f,這不是很清楚你想要什麼做 - 你正在嘗試合適的東西,並從結果中收集一些東西,但關於Model$cof的部分是指未定義的變量(您的Model只有a1b1c1條目)。假設你想實際收集cof並丟棄臨時代碼,get.f大概是這樣的:

M <- function(sampleData, offset) { 
    a1 = sampleData[,c(2:5,7,9)] + offset 
    b1 = sampleData[,c(2:4,6,8,7)] + offset 
    c1 = b1+a1 
    list(a1=a1,b1=b1,c1=c1) 
} 

get.f <- function(asim,Model,M){ 
    sse <-c() 
    for(i in 1:asim){ 
     set.seed(i) 
     Samdat <- dat[sample(1:nrow(dat),nrow(dat),replace=T),] 
     Y <- Samdat[,1] 
     model <- Model() 
     if(M==1){ 
      a2 <- model$a1 
      b2 <- model$b1 
      c2 <- model$c1 
      s<- a2+b2+c2 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      sse <-c(sse,cof) 
     } 
     else if(M==2){ 
      a2 <- model$a1 
      b2 <- model$b1 
      c2 <- model$c1 
      s<- c2+12 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      sse <-c(sse,cof) 
     } 
     else { 
      a2 <- model$a1 
      b2 <- model$b1 
      c2 <- model$c1 
      s<- c2+a2 
      fit <- lm(Y~s) 
      cof <- sum(summary(fit)$coef[,1]) 
      sse <-c(sse,cof) 
     } 
    } 
    return(sse) 
} 


get.f(10,Model=M1,M=1) 
get.f(10,Model=M2,M=2) 
get.f(10,Model=M3,M=3) 

這仍然是非常重複,所以我們爲什麼不想想一分鐘?你所做的一切就是計算你的樣品中的一列,以便適合你的樣品。我不明白你爲什麼需要在M函數中進行計算,然後在get.f(取決於你使用的是哪個特定的M)中提取單個值 - 這似乎表明提取應該更多地成爲M ...但是如果你需要將它們分開,好吧,我們使用單獨的提取功能。仍來自於在你的代碼大小的一半合理寫R:

# Set up test data 
dat <- cbind(Y=rnorm(20),rnorm(20),runif(20),rexp(20),rnorm(20),runif(20), rexp(20),rnorm(20),runif(20),rexp(20)) 
nam <- paste("v",1:9,sep="") 
colnames(dat) <- c("Y",nam) 

# calculate a1..c1 from a sample 
M <- function(sampleData, offset) { 
    a1 = sampleData[,c(2:5,7,9)] + offset 
    b1 = sampleData[,c(2:4,6,8,7)] + offset 
    c1 = b1+a1 
    list(a1=a1,b1=b1,c1=c1) 
} 

# create a fixed-offset model from the variable offset model by fixing offset 
makeModel <- function(offset) function(sampleData) M(sampleData, offset) 

# run model against asim subsamples of data and collect coefficients 
get.f <- function(asim,model,expected) 
    sapply(1:asim, function (i){ 
     set.seed(i) 
     Samdat <- dat[sample(1:nrow(dat),nrow(dat),replace=T),] 
     Y <- Samdat[,1] 
     s <- expected(model(Samdat)) 
     fit <- lm(Y~s) 
     sum(summary(fit)$coef[,1]) 
    }) 

# list of models to run and how to extract the expectation values from the model reslts 
todo <- list(
     list(model=makeModel(0), expected=function(data) data$a1+data$b1+data$c1), 
     list(model=makeModel(2), expected=function(data) data$c1+12), 
     list(model=makeModel(8), expected=function(data) data$c1+data$a1)) 

sapply(todo, function(l) { get.f(10, l$model, l$expected)}) 
+0

謝謝你的回答。我試圖創建一個類似於我想要做的例子。第一:M1-M3功能相似但不相同,我給每一個添加了不同的常數。但是在我編碼的實際工作中,他們有不同的矩陣。我正在嘗試的是在get.f函數中調用這些函數(M1-M3)以創建具有M1-M3的新矩陣。我會在對數據進行採樣後執行此操作,以便適應新模型。我不明白你說的是什麼可怕的部分。我有更多的M1 - M3(有M1 - M30),所以我不能只是在get.f函數中編寫它們。 –

+0

我擴大了我的答案。 – themel

+0

我喜歡敘述,+1。 – flodel