【问题标题】:Automatic use of large numbers of combinations of parameters as input for a function?自动使用大量参数组合作为函数的输入?
【发布时间】:2017-03-12 15:15:58
【问题描述】:

我正在尝试在 R 中模拟大量分布,因为我正在为不同的分布参数生成分位数。我想创建一个包含大量这些参数组合的数据集。例如(使用正态分布):

df<-data.frame(matrix(ncol=104,nrow=2))
colnames(df)<-c(as.character(seq(0,1,0.01),"type","mean","sd"))

这给了我一个数据框,其中包含 0.01 步中从 0 到 1 的分位数的 101 列以及“type”、“mean”和“sd”的三个附加列(这是使用正态分布时的唯一参数)。

现在让我们为正态分布族中的两个成员生成分位数:

qnorm.0.1<-qnorm(seq(0,1,0.01),0,1) #normal distribution / mean=0 /sd=1
qnorm.0.2<-qnorm(seq(0,1,0.01),0,2) #normal distribution / mean=0 /sd=2

现在我可以用两个向量填充我的数据框了:

df[1,]<-c(qnorm.0.1,"normal","0","1")
df[2,]<-c(qnorm.0.2,"normal","0","2")

这为我提供了我需要的格式。 但是,当我试图创建具有许多参数组合的大型数据集(例如,平均值从 1 到 10000 和 sd 从 1 到 10000 的每个组合)时,我将不得不想出一种自动化这个过程的方法。任何帮助表示赞赏。

谢谢!

【问题讨论】:

  • 你为什么不发布你的代码来展示你想用少量的参数组合做什么。
  • 您在寻找?expand.grid吗?
  • 好吧,对于我的示例,您可以使用 for 循环,例如:for (i in 1:2) { df[i,]&lt;-c(qnorm(seq(0,1,0.01),0,i),"normal","0",i) } 但是,我想使用超过 1 层的 for 循环和大量数字会使代码非常慢,很遗憾。
  • @Ben Bolker:谢谢你,这已经很有帮助了。 expand.grid 允许我将 for 循环保留在一层:comb&lt;-expand.grid(c(0:1),c(1:2)) for (i in 1:4){ df[i,]&lt;-c(qnorm(seq(0,1,0.01),comb$Var1[i],comb$Var2[i]),"normal",comb$Var1[i],comb$Var2[i]) } 但是,有没有办法更有效地做到这一点(即没有 for 循环)?
  • 我在想,你需要的是参数组合还是排列?因为组合会导致例如 1 mean, 2 sd,但不是相反,我认为你需要排列,不是吗?

标签: r


【解决方案1】:

也许这会有所帮助,

library(data.table)
## Generate Parameters
param <- 0:9
## Generate Combinatios of par.
cb <- combn(par,2, simplify = F)
n <- length(cb)
## Input the parameters
DT <- lapply(cb, function(x){data.table(rbind(qnorm(seq(0, 1, 0.01),x)))})
DT <- rbindlist(DT)
DT[, `:=`(type=rep("normal",n),
          mean = unlist(cb)[seq(1, n*2, 2) ],
          sd = unlist(cb)[seq(2, n*2, 2) ])]
## Change names
setnames(DT, c(paste0("qnorm", seq(0, 1, 0.01)), "type", "mean", "sd"))
dim(DT)
[1]  45 104

head(DT[,95:104])
   qnorm0.94 qnorm0.95 qnorm0.96 qnorm0.97 qnorm0.98 qnorm0.99 qnorm1   type mean sd
1:  1.554774  2.644854  1.750686  2.880794  2.053749  3.326348    Inf normal    0  1
2:  1.554774  3.644854  1.750686  3.880794  2.053749  4.326348    Inf normal    0  2
3:  1.554774  4.644854  1.750686  4.880794  2.053749  5.326348    Inf normal    0  3
4:  1.554774  5.644854  1.750686  5.880794  2.053749  6.326348    Inf normal    0  4
5:  1.554774  6.644854  1.750686  6.880794  2.053749  7.326348    Inf normal    0  5
6:  1.554774  7.644854  1.750686  7.880794  2.053749  8.326348    Inf normal    0  6

当然,您可以增加参数数量或更改分布函数,但结果会相似。

【讨论】:

  • 谢谢,这是一个不错的起点。不幸的是,其他发行版(例如 qpareto() )不会采用 list 参数,但我相信我会找到解决方法:)
  • 我不认为你会有问题,因为lapply 正在获取列表的每个元素,在这种情况下它们是向量。但是,也许你可以给我举个例子。
  • 您可以尝试将代码与 rmutil 包中的 qpareto() 一起使用,而不是 qnorm(),它会告诉您,缺少一个参数,我觉得这很有趣,因为两个发行版都会取两个参数。但是,您可以像这样使用mapply() 来解决问题:var&lt;-cb var1&lt;-lapply(var, "[", c(1)) var2&lt;-lapply(var, "[", c(2)) DT&lt;-data.table(rbind(mapply(function(X,Y) {qpareto(seq(0,1,0.01),X,Y)}, X=var1, Y=var2)))
  • 你真的不需要mapply,它比lapply慢。勾选此项,将参数组合生成为列表cb &lt;- combn(1:5, 2, simplify = F);然后创建一个相同长度的空列表out &lt;- vector("list", length(cb));使用 lapply 将参数作为函数传递,并将它们拆分到 qpareto 内; out &lt;- lapply(cb, function(x){data.table(rbind(qpareto(seq(0,1,0.01), x[1], x[2])))})
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-15
相关资源
最近更新 更多