[R] reference generated var name in loop

Greg Snow 538280 @end|ng |rom gm@||@com
Fri May 26 18:00:45 CEST 2023


Using the `assign` function is almost always a sign that you are
making things more complicated than is needed.  It is better to work
directly with lists, which make it much easier to set and get names.

Your code and description can be done pretty simply using the `lapply
function (often easier than using a loop if the desire is to save the
output of each iteration), here is one example:

parms <- c(a=4, b=6, c=11)

tmp1 <- lapply(parms, function(mu){
  rnorm(5, mu, 0.25)
})

names(tmp1) <- paste0(names(parms), "_r")
ranvec <- as.data.frame(tmp1)
ranvec

We can skip the temporary variable(s) by using pipes like this:

parms |>
  lapply( rnorm, n=5, sd=0.25 ) |>
  setNames( paste0(names(parms), "_r")) |>
  as.data.frame()

Your line using `sub` does not do anything.  While the `=` sign was
used to create the vector with names, the vector itself does not
contain any `=` signs and so there is no reason to try to remove
anything.  The `parms` vector already contains the numbers that you
are trying to extract (plus a names attribute which will be ignored
when not needed, so usually there is no reason to remove the names).

The `lapply` function runs the function passed in (an anonymous
function in the first example, the `rnorm` function in the second) on
each element of the vector/list passed in as the first argument and
stores each result as an element in a list, which is then returned
(and in my examples named then converted to a data frame).

The `sapply` function would combine the resulting vectors into a
matrix, and would handle the naming automatically, so something as
simple as:

sapply(parms, rnorm, n=5, sd=0.25)

may do what you want (you could pipe that to `as.data.frame` if you
really need a data frame).


The purrr package (part of the tidyverse) gives some additional
functions similar to `lapply` and `sapply` but with extra bells and
whistles.

If you really want to use a loop, then take advantage of the fact that
the data frame is a special case of a list and try something like:

ranvec <- data.frame(row.names=1:5)
for(i in seq_along(parms)) {
  tmp.nm <- paste0(names(parms)[i], '_r')
  ranvec[[tmp.nm]] <- rnorm(5, parms[i], 0.25)
}

or

ranvec <- data.frame(row.names=1:5)
for(nm in names(parms)) {
  tmp.nm <- paste0(nm, '_r')
  ranvec[[tmp.nm]] <- rnorm(5, parms[nm], 0.25)
}


On Fri, May 26, 2023 at 8:50 AM Evan Cooch <evan.cooch using gmail.com> wrote:
>
> Greetings --
>
> I'm trying to write some code that basically does the following:
>
> 1\ user inputs a list of parameter names, and parameter values.
>
> 2\ code parses this list, extracting parameter names and values separately
>
> 3\ loops over the number of parameters, and for each parameter,
> generates something (say, rnorm) based on the value corresponding to
> that parameter.
>
> 4\ assigns a new name to the vector of rnorm data, where the name is a
> permutation of the original parameter name. In the example (below) I
> simply past "_r" to the original parameter name (to indicate, say, its
> some rnorm values associated that that variable).
>
> 5\the 'I'm stumped' part -- output the newly named vector into something
> (say, data.frame), which requires being able to reference the newly
> named vector, which is what can't figure out how to accomplish.
>
> Here is a MWE of sorts -- the starting list of parameter names and
> values is in a list I call parms.
>
>   parms <- c(a=4,b=6,c=11) # list of parms user could pass to a function
>
>   nvars <- names(parms)  # extract parameter names
>
>   vals <- sub("\\=.*", "", parms) # extract parameter values
>
>   n <- length(parms) # determine number of parameters
>
>   ranvec <- data.frame() # to store stuff from loop
>
>   for (i in 1:n) {
>     pn <- nvars[i]; # get name of parm variable
>     rn <- rnorm(5,as.numeric(vals[i]),0.25) # generate rnorm based on
> parm value
>     assign(paste(pn, "_r", sep=""),rn) # creates a_r, b_r, c_r...
>     ** here is where I want to output to ranvec, but I can't see how to
> do it since the loop doesn't know the name of the new var created in
> preceding step...**
>   }
>
>
> In the end, I want to create a data frame containing rnorm deviates for
> each of a set of user-specified variables, which I can reference in some
> fashion using a permuted version of the original variable name.
>
> Suggestions?
>
> Many thanks...
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.



-- 
Gregory (Greg) L. Snow Ph.D.
538280 using gmail.com



More information about the R-help mailing list