I would like to make the following code run:
mu = 5
rnorm2 <- function(N) rnorm(N, mean = mu, sd = 1)
And then be able to use the rnorm2 function regardless of the presence of the mu variable in the environment. In other words, set the value of the 'mean' argument with the "mu" value once and for all.
Is that possible ?
CodePudding user response:
You could make a copy of rnorm
and set the function defaults with formals
:
mu <- 5
rnorm2 <- rnorm
formals(rnorm2)$mean <- mu
Output
> set.seed(1)
> rnorm2(5)
[1] 4.373546 5.183643 4.164371 6.595281 5.329508
> formals(rnorm2)
$n
$mean
[1] 5
$sd
[1] 1
CodePudding user response:
1) local with free variable We can use local
to capture the prior value of mu
.
Note that the cached value of mu
is mu_
and is stored in the environment in which rnorm3
is defined at the time it was defined as opposed to the environmnent and time when rnorm3
is first run.
If it were desired to later set it then we could use environment(rnorm3)$mu_ <- 5
and we can query the cached value at any time using environment(rnorm3)$mu_
.
set.seed(123)
mu = 5
rnorm3 <- local({
if (exists("mu")) mu_ <- mu
function(N) rnorm(N, mean = mu_, sd = 1)
})
rnorm3(1)
## [1] 4.439524
rm(mu)
rnorm3(1)
## [1] 4.769823
2) local using arguments Relying on free variables, i.e. variables such as mu
which are used but not defined in the function, may not be the best approach as it makes it harder to debug and it may be preferable to use arguments instead. This uses the mu
argument, if specified, and uses the value specified the last time rnorm4
was called if not.
rnorm4 <- local({
mu_ <- NA
function(N, mu = mu_) {
mu_ <<- mu
rnorm(N, mu, 1)
}
})
set.seed(123)
rnorm4(1, 5)
## [1] 4.439524
rnorm4(1)
## [1] 4.769823
3) proto Another approach is to use object oriented programming. The proto package makes this particularly easy since it can define objects without the overhead of creating classes to instantiate them from. We create an object p
with a method rnorm
(which calls rnorm
in stats) and an attribute mu
. p$rnorm
will look into p
for mu
so we can delete mu
outside p
. Note that the the notation p$norm(1)
says to pass the object p
as the first argument and 1 as the second argument. We can redefine or query mu
at any time by setting or querying p$mu
.
library(proto)
p <- proto(rnorm = function(., N) stats::rnorm(N, mu, 1))
set.seed(123)
mu <- 5
p$mu <- mu
rm(mu)
p$rnorm(1)
## [1] 4.439524
4) options Another possibility is to store mu
as an R option.
set.seed(123)
options(mu = 5)
rnorm5 <- function(N, mu = getOption("mu")) rnorm(N, mu, 1)
rnorm5(1)
## [1] 4.439524
CodePudding user response:
Will this work?
rnorm2 <- function(N, mu = 5, sd = 1) rnorm(N, mean = mu, sd = sd)
This just sets the default mu and sd to 5 and 1 respectively.
You can deviate from the default with rnorm2(N, 7, 2)
(or rnorm2(N, mu = 7, sd = 2)
) which would have a mean of 7 and an sd of 2.
But if you just do rnorm2(N)
it will have a mean of 5 and an sd of 1.
(I agree with the other answers here also, but I wonder if you were looking for a simpler answer and didn't ask the question just right.)