I'm programming a Monte-Carlo Simulation that should give the user quite some flexibility. Consequently, I want the user to be able to specify the concrete probability distribution of the random numbers before the simulation is run. However, at this time it is not known to the user how many random numbers are needed.
我正在编写蒙特卡罗模拟,应该给用户一些灵活性。因此,我希望用户能够在模拟运行之前指定随机数的具体概率分布。然而,此时用户不知道需要多少随机数。
My idea is now to get a call-object from user that creates ONE random number and then create as many of those random numbers as needed internally. However, except for a loop I can't get any other solution to work, but have the feeling that this is because of me missing something. So basically, I have two questions:
我的想法是从用户那里获得一个调用对象,创建一个随机数,然后根据需要在内部创建尽可能多的随机数。但是,除了一个循环我不能得到任何其他解决方案,但感觉这是因为我错过了一些东西。基本上,我有两个问题:
1) Is the idea with the call-object a good one? I'm still working on the project so I could still change the set-up, but I need a very intuitive solution for the user.
1)调用对象的想法是好的吗?我还在研究这个项目,所以我仍然可以改变设置,但我需要一个非常直观的解决方案。
2) If it is a good idea, is there are more elegant way to expand the random number to a vector of size nrMCS?
2)如果这是一个好主意,是否有更优雅的方法将随机数扩展为大小为nrMCS的向量?
Let's make an example:
我们举一个例子:
#That's what I would get from the user with my current set-up:
rnd_call <- call("rnorm", 1, mean=0.1, sd=0.01)
#To create nrMCS random numbers, that's my best shot so far:
nrMCS <- 100
rnd_vec <- as.numeric(nrMCS)
for (i in 1:nrMCS){rnd_vec[i] <- eval(rnd_call)}
rnd_vec
[1] 0.09695170 0.11752132 0.11548925 0.11205948 0.10657986 0.12017120 0.09518435
...
#Question: Is there are more elegant way?
#I tried the following, but it fails for certain reasons
rep(eval(rnd_call), nrMCS) #DOES NOT WORK: Repeats ONE random number
[1] 0.1105464 0.1105464 0.1105464 0.1105464 0.1105464 0.1105464 0.1105464 0.1105464
...
eval(rep(rnd_call, nrMCS)) #DOES NOT WORK
Error in rnorm(1, mean = 0.1, sd = 0.01, rnorm, 1, mean = 0.1, sd = 0.01, :
formal argument "mean" matched by multiple actual arguments
1 个解决方案
#1
5
I think a more idiomatic way to do this would be to take an r*
function and a list of arguments. Whenever you can avoid calling eval
, you should. Something like this:
我认为更为惯用的方法是采用r *函数和参数列表。每当你可以避免调用eval时,你应该这样做。像这样的东西:
rnd_fun <- rnorm
rnd_args <- list(mean=0.1,sd=0.01)
nrMCS <- 100
rnd_vec <- do.call(rnd_fun,c(list(n=nrMCS),rnd_args))
(this relies on the convention in R that the first argument to an r*
(random deviate generator) function is always n
, the number of deviates required ...)
(这依赖于R中的约定,r *(随机偏差生成器)函数的第一个参数总是n,所需的偏差数...)
Furthermore, calling rnd_fun
once with n=nrMCS
is generally much more efficient than calling it nrMCS
times ...
此外,使用n = nrMCS调用rnd_fun一次通常比调用nrMCS次更有效...
library(rbenchmark)
nrMCS <- 10000
benchmark(single_call=do.call(rnd_fun,c(list(n=nrMCS),rnd_args)),
mult_call=replicate(nrMCS,do.call(rnd_fun,c(list(n=1),rnd_args))))
test replications elapsed relative user.self sys.self
2 mult_call 100 11.135 91.27049 11.084 0.004
1 single_call 100 0.122 1.00000 0.080 0.036
#1
5
I think a more idiomatic way to do this would be to take an r*
function and a list of arguments. Whenever you can avoid calling eval
, you should. Something like this:
我认为更为惯用的方法是采用r *函数和参数列表。每当你可以避免调用eval时,你应该这样做。像这样的东西:
rnd_fun <- rnorm
rnd_args <- list(mean=0.1,sd=0.01)
nrMCS <- 100
rnd_vec <- do.call(rnd_fun,c(list(n=nrMCS),rnd_args))
(this relies on the convention in R that the first argument to an r*
(random deviate generator) function is always n
, the number of deviates required ...)
(这依赖于R中的约定,r *(随机偏差生成器)函数的第一个参数总是n,所需的偏差数...)
Furthermore, calling rnd_fun
once with n=nrMCS
is generally much more efficient than calling it nrMCS
times ...
此外,使用n = nrMCS调用rnd_fun一次通常比调用nrMCS次更有效...
library(rbenchmark)
nrMCS <- 10000
benchmark(single_call=do.call(rnd_fun,c(list(n=nrMCS),rnd_args)),
mult_call=replicate(nrMCS,do.call(rnd_fun,c(list(n=1),rnd_args))))
test replications elapsed relative user.self sys.self
2 mult_call 100 11.135 91.27049 11.084 0.004
1 single_call 100 0.122 1.00000 0.080 0.036