你可以向我解释为什么代码抱怨说Samdat找不到?
我试图在模型之间切换,所以我声明了一个包含这些特定模型的函数,我只需要将此函数作为函数中的一个参数调用,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)
Run Code Online (Sandbox Code Playgroud)
您可能想要查看R范围规则.特别是,没有理由期望在函数中定义的变量在其他函数中可见.
您可能会感到困惑,因为全局环境(即所有函数外的顶层)是此规则的一个例外.我不打算进入你的其他问题,但让我注意,整个剧本看起来很搞砸了我-即M1以M3基本上是一个函数,复制/粘贴的一叠中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)
}
Run Code Online (Sandbox Code Playgroud)
如果你坚持定义别名,你也可以做类似的事情
M1 <- function(sampleData) M(sampleData, 0)
M2 <- function(sampleData) M(sampleData, 2)
M3 <- function(sampleData) M(sampleData, 8)
Run Code Online (Sandbox Code Playgroud)
这已经不那么重复,但理想情况下你希望计算机为你做重复(干!):
offsets <- c(0,2,8)
Models <- sapply(offsets, FUN=function(offset) function(sampleData) M(sampleData, offset))
Run Code Online (Sandbox Code Playgroud)
看着get.f,这不是很清楚你想要做什么-你要适应的东西,收集结果的东西,但对部分Model$cof指的是未定义的变量(你Model只是有a1,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)
Run Code Online (Sandbox Code Playgroud)
那仍然非常重复,那么我们为什么不考虑一下呢?您对样品所做的一切就是从它们中计算出一列用于您的样品.我不明白为什么你需要在一个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)})
Run Code Online (Sandbox Code Playgroud)
你打电话时
get.f(10, Model=M1(), M=1)
Run Code Online (Sandbox Code Playgroud)
您的M1函数会立即被调用。它死了,因为在M1你的身体内部正在使用Samdat它只是稍后在get.f.
不知何故,您需要M1 在 Samdat定义之后调用。这样做的一种方法是使M1(函数)成为参数get.f并从内部调用函数get.f:
get.f <- function(asim, Model.fun, M) {
...
Sambat <- ...
Model <- Model.fun()
...
}
get.f(10, Model.fun = M1, M=1)
Run Code Online (Sandbox Code Playgroud)
此外,一般来说,使用全局变量是糟糕的编程,即让您的函数使用在其范围之外定义的变量。相反,建议将函数使用的所有内容作为输入参数传递。您的代码中有两种这样的情况:M1( M2, 和M3) useSamdat和get.fuses 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)
Run Code Online (Sandbox Code Playgroud)
即跳出最后一两件事:如果定义s(我收集下switch()是关系到Model你使用,然后再考虑合并的定义Model和s在一起:添加s到您的列表输出M1,M2,M3功能,因此s可以只被定义为s <- Model$s,然后您可以将M输入放到get.f.