Home > database >  Parametrize a function with a variable. Then delete the variable
Parametrize a function with a variable. Then delete the variable

Time:10-31

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.)

  • Related