Question

a R novice is once again seeking for help.

General situation: I am currently creating a script, I got several data frames per experiment. The experiments vary in time-steps of measurements and number of reactors, therefore I need two dimensional flexibility of my script to "massage" data into the right shape for the desired tests, and draw the necessary data from multiple data frames. Unfortunately I choose to use for loops to account for this, which I see now is bad practice in R, but I have gotten to fare to change directions now.

The Problem: I try to achieve that one dimensional matrix are named by the objects names, inside a for loop, I need them to be in matrix format because of further functions I want to apply.

# Simple but non- flexible examples of what I want to do:

# creates two matrix objects
a1 <- matrix(c(1,2,3,4,5))
a2 <- matrix(c(1,2,3,4,5))

#names header of the objects name
colnames(a1) <- "a1"
colnames(a2) <- "a2"

this works, but I need it to work with in a for loop...

# here are the two flexible but non- working approaches of mine

# creates two matrix objects
a1 <- matrix(c(1,2,3,4,5))
a2 <- matrix(c(1,2,3,4,5))

# should name object according to progress in loop
for(i in 1:2)
{
 assign(colnames(paste("a",i,sep="",collapse="")),do.call("c",list(paste("a",i,sep=""))))
}

which isn’t the proper use of assign and creates an error. the second attempt doesn't create an error but doesn't work either, it creates empty objects

# creates two matrix objects
a1 <- matrix(c(1,2,3,4,5))
a2 <- matrix(c(1,2,3,4,5))

# should name object according to progress in loop
for(i in 1:2)
    {
      assign(paste("a",i,sep="", colapse=""),do.call("colnames",list(paste("a",i,sep="", colapse=""))))
    }

My conclusion: I do not understand the proper way of combining assign, and colnames, If anyone got suggestion how I could get it up and running, this would be awesome.

So fare I searched for: R combining assign and colnames inside for loop, R using assign and colnames, R naming data with for loops,... but unfortunately didn’t manage to extrapolate solutions to my problem.

Était-ce utile?

La solution

The following is a function that, by default, will take any objects in the parent environment that have a name that starts with a followed by numbers, check that they are one column matrices, and if they are, name the columns with the name of the object.

a1 <- matrix(c(1:5))
a2 <- matrix(c(1:5))
name_cols()
a1
#      a1
# [1,]  1
# [2,]  2
# ...
a2
#      a2
# [1,]  1
# [2,]  2
# ...

And here is the code:

name_cols <- function(pattern="^a[0-9]+", env=parent.frame()) {
  lapply(
    ls(pattern=pattern, envir=env),
    function(x) {
      var <- get(x, envir=env)
      if(is.matrix(var) && identical(ncol(var), 1L)) {
        colnames(var) <- x
        assign(x, var, env)
  } } )
  invisible(NULL)
}

Note I chose specification by pattern, but you can easily change this to be by specifying the names of the variable (instead of using ls, just pass the names and lapply over those), or potentially even the objects (though you have to use substitute for that, and the wiseness of this becomes questionable).

More generally, if you have several related objects on which you will be performing related analysis (e.g. in this case modifying columns), you should really consider storing them in lists rather than at the top level. If you do this, then you can easily use the built in *pply functions to operate on all your objects at once. For example:

a.lst <- list(a1=matrix(1:5), a2=matrix(1:5))
a.lst <- lapply(names(a.lst), function(x) {colnames(a.lst[[x]]) <- x; a.lst[[x]]})
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top