【问题标题】:Function inputs from a list列表中的函数输入
【发布时间】:2015-01-21 07:04:42
【问题描述】:

如何运行一个函数(在 R 中),其中一些输入是从列表(或数据框)中提取的?我认为这比运行 for 循环更有效吗?

我正在运行模拟并想要更改变量值,但由于它们需要很长时间才能运行,我希望它们在一夜之间运行并自动勾选不同的值。

这是函数的代码:

n = 10000         
mu = 0                          
sd = 1                          
n.sub = 100                       
iboot = 100
isim = 1000     ### REDUCED FOR THIS EXAMPLE ###
var.values <- NULL         
var.values.pop <- NULL  

hist.fn <- function(n,mu,sd,n.sub,iboot)
{ 
Pop <- rnorm(n,mu,sd)
var.pop <- var(Pop)                       
Samp <- sample(Pop, n.sub, replace = FALSE)  
var.samp <- var(Samp)                                         
for(i in 1:isim) {            
  for(j in 1:iboot) {         
    Boot <- sample(Samp, n.sub, replace = TRUE)           
    var.values[j] <- var(Boot)                                  
    }                                                               
  Samp <- sample(Pop, n.sub, replace = FALSE)         
  var.values.pop[i] <- var(Samp)                                   
  }                                                               
hist.pop <- hist(var.values.pop,plot=F)
hist.boot <- hist(var.values,plot=F)
#mypath = file.path("C:", "Output", paste("hist.boot_n.", n.sub, "_var.", sd^2, "_isim.", isim, "_iboot.", iboot, ".wmf", sep=""))
#win.metafile(file=mypath)
plot.new()   #### ADDED FOR THIS EXAMPLE INSTEAD OF OUTPUTTING TO FILE ####
plot(hist.pop, freq=FALSE, xlim=range(var.values.pop, var.values), ylim=range(hist.pop$density, hist.boot$density), main = paste("Histogram of variances \n n=",n.sub," mu=",mu,"var=",sd^2,"\n n.sim=",isim,"n.boot=",iboot,"\n"), cex.main=0.8, xlab="Variance", col="red") 
plot(hist.boot, freq=FALSE, col="blue", border="blue", add=T, density=20, angle=45) 
abline(v=var.pop, lty=2, col="black", lwd=2)
 legend("topright", legend=c("sample","bootstrap"),col=c("red","blue"),lty=1,lwd=2,bty="n",cex=0.7)
#dev.off()
}

hist.fn(n,mu,sd,n.sub,iboot)

然后我希望通过运行以下值来更改 sd、n.sub 和 iboot:

sd <- c(1,10,100,1000)
n.sub <- c(4,10,100,1000)
iboot <- c(100,1000,10000)

【问题讨论】:

    标签: r list function dataframe simulation


    【解决方案1】:

    也许是这样的?

        n = 10000         
        mu = 0                          
        sd = 1                          
        n.sub = 100                       
        iboot = 100
        isim = 1000 
        sd <- c(1,10,100,1000)
        n.sub <- c(4,10,100,1000)
        iboot <- c(100,1000,10000)
        # hist.fn parameters: n,mu,sd,n.sub,iboot
        params <- expand.grid(n = n, mu = mu, sd = sd, 
                  n.sub = n.sub, iboot = iboot)
        apply(params, 1, FUN = function(x) do.call(hist.fn, as.list(x) ) )
    

    你可能想把这些:

        var.values <- NULL         
    var.values.pop <- NULL  
    

    在 hist.fn 内部,因为将值分配给函数外部的变量并不像您想象的那样工作。

    【讨论】:

    • 非常感谢,帮了大忙
    【解决方案2】:

    您应该使用do.call,它将使用列表中的参数应用函数。我已经简化了您的示例,以便为示例运行更少的循环。您可以修改脚本的printline 以监控您的进度以完成更大的工作:

    # The function
    hist.fn <- function(n,mu,isim,sd,n.sub,iboot)
    { 
      Pop <- rnorm(n,mu,sd)
      var.pop <- var(Pop)                       
      Samp <- sample(Pop, n.sub, replace = FALSE)  
      var.samp <- var(Samp)
      var.values <- NaN*seq(isim) # sets up an empty vector for results
      var.values.pop <- NaN*seq(isim) # sets up an empty vector for results
      for(i in seq(isim)) {            
        for(j in seq(iboot)) {         
          Boot <- sample(Samp, n.sub, replace = TRUE)           
          var.values[j] <- var(Boot) 
          print(paste("i =", i, "; j =", j))
        }                                                               
        Samp <- sample(Pop, n.sub, replace = FALSE)         
        var.values.pop[i] <- var(Samp)                                   
      }                                                               
      list(var.values=var.values, var.values.pop=var.values.pop) #returns results in the form of a list
    }
    
    # Global variables
    n = 100         
    mu = 0                          
    isim = 10
    
    # Changing variables
    sd <- c(1,10,20,30)
    n.sub <- c(4,10,20,30)
    iboot <- c(100,200,300,400)
    
    df <- data.frame(sd=sd, n.sub=n.sub, iboot=iboot)
    res <- vector(mode="list", nrow(df)) # sets up an empty list for results
    for(i in seq(nrow(df))){
      res[[i]] <- do.call(hist.fn, c(n=n, mu=mu, isim=isim, df[i,]) ) 
    }
    res # show results
    

    【讨论】:

    • 感谢使用 do.call 的建议
    【解决方案3】:
    sd <- 1:3
    n.sub <- 4:6
    iboot <- 7:9
    
    funct1<-function(x,y,z) print(x+y+z)
    
    for (i in 1:length(sd)){
      funct1(sd[i],n.sub[i],iboot[i])
    }
    

    只是一个例子。用循环来做。

    【讨论】:

    • 谢谢,但我试图避免使用循环。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 2013-01-03
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 2022-12-07
    • 2022-11-15
    相关资源
    最近更新 更多