6

Samdatコードが見つからないと文句を言う理由を説明していただけますか?

モデルを切り替えようとしているので、これらの特定のモデルを含む関数を宣言しました。この関数をget.f、リサンプリングによってモデルの各計画行列の構造が変更される関数の引数の1つとして呼び出す必要があります。コードSamdatは、見つかったときに見つからないと文句を言います。

また、設定if(Model == M1())する別の引数を作成する代わりに、条件付きステートメントを作成する方法はありますか?Mif(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)
4

2 に答える 2

11

R スコープ ルールを参照してください。特に、関数で定義した変数が他の関数で見えると期待する理由はありません。

グローバル環境 (つまり、すべての関数の外側のトップレベル) はこの規則の例外であるため、混乱するかもしれません。他の質問には触れませんが、スクリプト全体が非常に混乱しているように見えることに注意してください。つまり、本質的M1M3は 1 つの機能であり、コピー/貼り付けの塊get.fは間違いなくひどいものです。あなたがやろうとしていることが何であれ、より複雑でない方法で書くことは間違いありません。

最初に sを見てみましょうM。パラメータを持つ 1 つの関数ではないのはなぜですか? スコープの問題の解決策を含めて、2つのパラメーターを作成します-

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、何をしようとしているのかはっきりしていません。何かを当てはめ、結果から何かを収集しようとしていますが、 about の部分Model$cofは未定義の変数を参照しています (あなたModela1,b1と のc1エントリしか持っていません)。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)

それはまだひどく繰り返されているので、少し考えてみませんか? サンプルで行っていることは、それらから 1 つの列を計算して近似に使用することだけです。M関数で計算を行ってから、(使用している特定の M に応じて) で単一の値を抽出する必要がある理由がわかりません。get.fこれは、抽出がむしろ 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)})
于 2012-09-01T13:22:27.667 に答える
5

電話すると

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

M1関数がすぐに呼び出されます。の本体で後で定義されるだけM1を使用しているため、それは死にます。Samdatget.f

どういうわけか、が定義されたM1 後に呼び出す必要があります。 Samdatこれを行う 1 つの方法は、M1(関数) を引数にしてget.f、内部から関数を呼び出すことですget.f

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

また、一般に、グローバル変数を使用する、つまり、関数がそのスコープ外で定義された変数を使用するようにすることは、プログラミングでよくありません。代わりに、関数が使用するすべてのものを入力引数として渡すことをお勧めします。M1コードには、 ( M2, とM3) useSamdatget.fusesの 2 つのケースがあります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にマージすることを検討してください: , ,関数のリスト出力に追加して、 ,として定義できるようにします。その後、入力を にドロップできます。ModelssM1M2M3ss <- Model$sMget.f

于 2012-09-01T15:43:44.987 に答える