Accessing and using names of an object when using llply

435 views
Skip to first unread message

Greg King

unread,
Jan 16, 2013, 6:26:51 PM1/16/13
to manip...@googlegroups.com
I'm not sure this is the best wording for the question (and maybe my vocabulary is leading to a lack of applicable search results within this and other help forums), but I'm hoping the example below makes sense and a solution can be proposed. 

I have an ordered time series object (in this case a zoo object) that I am applying a function to using llply. The output is a list consisting of the same number of components as there are columns in the zoo object (in my case each is a site). Each of these list components is a data.frame with the same number of columns. I like llply because it preserves the names of the original object as the names of the list. However, what I'd like to do is create a column in each data.frame with the site names. My purpose is that I'd like to use a ldply later to pull information from each data.frame for further processing and the name could come in handy calling other data in the environment.

For the life of me, I can't figure out how to get the name information into the data.frame (although I feel it should be rather straightforward). I'm not exactly sure, but I think because of the splitting behaviour of plyr there is no name during the processing (although it must be retained somewhere as it is present in the list output).

Here is some dummy code that I think encapsulates the problem and provides an idea of what I'm hoping to achieve:

library(zoo)
library(plyr)

t.zoo <- merge.zoo("A" = zoo(rnorm(5), order.by=seq_len(5)), "B" = zoo(rnorm(5), order.by=seq_len(5)), "C" = zoo(rnorm(5), order.by=seq_len(5)))
t.list <- llply(t.zoo, function(i) data.frame(x=i+2, y=i-2, z=i+10)) # This works
t.list <- llply(t.zoo, function(i) data.frame(x=i+2, y=i-2, z=i+10, q=names(i))) #This fails because it doesn't find the names

names(t.zoo) # This returns the names of the zoo object
names(t.zoo)[,1] # But this returns NULL because when a single column is selected (as I think llply does) it no longer appears to have a dimnames attribute

# Ideally, my output would be:

t.list.goal <- list("A" = data.frame(x=rnorm(5), y=rnorm(5), z=rnorm(5), q=rep("A", 5)), "B" = data.frame(x=rnorm(5), y=rnorm(5), z=rnorm(5), q=rep("B", 5)), "C" = data.frame(x=rnorm(5), y=rnorm(5), z=rnorm(5)), q=rep("C", 5))

Thanks for any help. 

James McCreight

unread,
Jan 17, 2013, 12:43:38 AM1/17/13
to Greg King, manip...@googlegroups.com
Hi Greg-

this seems to come up fairly regularly. many people expect to be able to get the name in the function. it seems reasonable to me, i asked this question once. maybe one day? i'm not sure the mechanism for it however.

the answer is to simply iterate on a list of names which are those of your original list and named the same. then use the lexical scoping of R to get your variable from the original list by name. 

i do this so often that I wrote the following function to make my life easier

namedList <- function(vec, names=vec) {
  l <- as.list(vec)
  names(l) <- names
  l
}

so you end up doing this kind of thing to get what you're describing

originalList <- list( a=list(a1=1,a2=2), b=list(b1=3,b2=4))
llply( namedList(names(originalList)), 
        function(name) {originalList[[name]]$name <- name 
        originalList[[name]]} )

totally contrived, but i think you get the point. 

you could also iterate on index, but I think that using names is preferable in general.

those are my 2cents.

James


--
You received this message because you are subscribed to the Google Groups "manipulatr" group.
To view this discussion on the web visit https://groups.google.com/d/msg/manipulatr/-/bAFM80rjH5EJ.
To post to this group, send email to manip...@googlegroups.com.
To unsubscribe from this group, send email to manipulatr+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/manipulatr?hl=en.



--
-
******************************************************************************
James McCreight                               
cell: (831) 261-5149
office: (303) 735-4953
VoIP (to cell): (720) 432-2166 
Reply all
Reply to author
Forward
0 new messages