Re: [R] name returned by lapply

From: Gavin Simpson <>
Date: Fri, 18 Jul 2008 13:39:10 +0100

On Fri, 2008-07-18 at 14:19 +0200, Antje wrote:
> Hi Gavin,
> thanks a lot for your answer.
> Maybe I did not explain very well what I want to do and probably chose a bad
> example. I don't mind spaces or names starting with a number. I could even name it:
> "Hugo1", "Hugo2", ...
> My biggest problem is, that not only the values are calculated/estimated within
> my function but also the names (Yes, in reality my funtion is more complicated).
> Maybe it's easier to explain like this. the parameter x can be a coordinate
> position of mountains on earth. Within the funtion the height of the mountain
> is estimated and it's name.
> In the end, I'd like to get a list, where the entry is named like the mountain
> and it contains its height (or other measurements...)
> > ## now that we have a list, we change the names to what you want
> > names(ret) <- paste(1:10, "info_within_function")
> so this would not work, because I don't have the information anymore about the
> naming...

OK, so you can't do what you want to do in the manner you tried, via lapply as you don't have control of how the list is produced once the loop over 1:10 has been performed. At the stage that 'test' is being applied, all it knows about is 'x' and it doesn;t have access to the list being built up by lapply().

The *apply family of functions help us to *not* write out formal loops in R, but here this is causing you a problem. So we can specify an explicit loop and fill in information as and when we want from within the loop

## create list to hold results
n <- 10
ret <- vector(mode = "list", length = n) ## initialise loop
for(i in seq_len(n)) {

    ## do whatever you need to do here, but this line just     ## replicates what 'test' did earlier     ret[[i]] <- c(1,2,3,4,5)
    ## now add the name in
    names(ret)[i] <- paste("Mountain", i, sep = "") }

Alternatively, collect a vector of names during the loop and then once the loop is finished do a single call to names(ret) to replace all the names at once:

n <- 10
ret <- vector(mode = "list", length = n) ## new vector to hold vector of names
name.vec <- character(n)
for(i in seq_len(n)) {

    ret[[i]] <- c(1,2,3,4,5)
    ## now we just fill in this vector as we go     name.vec[i] <- paste("Mountain", i, sep = "") }
## now replace all the names at once
names(ret) <- name.vec

This latter version is likely to more efficient if n is big so you don't incur the overhead of the repeated calls to names()

The moral of the story is to not jump to using *apply all the time to avoid loops. Loops in R are just fine, so use the tool that helps you do the job most efficiently *and* most transparently.

Take a look at the R Help Desk article by Uwe Ligges and John Fox in the current issue of RNews:

Which goes into this in much more detail


 Dr. Gavin Simpson             [t] +44 (0)20 7679 0522
 ECRC, UCL Geography,          [f] +44 (0)20 7679 0565
 Pearson Building,             [e]
 Gower Street, London          [w]
 UK. WC1E 6BT.                 [w]

______________________________________________ mailing list
PLEASE do read the posting guide
and provide commented, minimal, self-contained, reproducible code.
Received on Fri 18 Jul 2008 - 12:56:34 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Fri 18 Jul 2008 - 13:31:57 GMT.

Mailing list information is available at Please read the posting guide before posting to the list.

list of date sections of archive