Hi, I have a question about applying a function recursively through a list. Suppose I have a list where the different elements have different levels of recursion:> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")),+ "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), + "c"=c("g", "h", "i")), + "B"=c("d", "e", "f"), "C"=c("g", "h", "i")))> test.list$I $I$A [1] "a" "b" "c" $I$B [1] "d" "e" "f" $I$C [1] "g" "h" "i" $II $II$A $II$A$a [1] "a" "b" "c" $II$A$b [1] "d" "e" "f" $II$A$c [1] "g" "h" "i" $II$B [1] "d" "e" "f" $II$C [1] "g" "h" "i" I would like to apply a function recursively to that list, in a way that the function does someting with each vector (eg. rev()) and returns a list of modified vectors that has the same structure as the input list, in my example: $I $I$A [1] "c" "b" "a" $I$B [1] "f" "e" "d" $I$C [1] "i" "h" "g" $II $II$A $II$A$a [1] "c" "b" "a" $II$A$b [1] "f" "e" "d" $II$A$c [1] "i" "h" "g" $II$B [1] "f" "e" "d" $II$C [1] "i" "h" "g" I understand that with a fixed number of recursion levels one can use lapply() in a nested way, but what if the numbers of recursion levels is not fixed or is different between the list elements as it is in my example? Any hint will be appreciated. Best, Georg
See ?rapply On Wed, 11 Jun 2008, Georg Otto wrote:> > Hi, > > I have a question about applying a function recursively through a > list. Suppose I have a list where the different elements have > different levels of recursion: > > >> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")), > + "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), > + "c"=c("g", "h", "i")), > + "B"=c("d", "e", "f"), "C"=c("g", "h", "i"))) > >> test.list > $I > $I$A > [1] "a" "b" "c" > > $I$B > [1] "d" "e" "f" > > $I$C > [1] "g" "h" "i" > > > $II > $II$A > $II$A$a > [1] "a" "b" "c" > > $II$A$b > [1] "d" "e" "f" > > $II$A$c > [1] "g" "h" "i" > > > $II$B > [1] "d" "e" "f" > > $II$C > [1] "g" "h" "i" > > > > I would like to apply a function recursively to that list, in a way > that the function does someting with each vector (eg. rev()) and > returns a list of modified vectors that has the same structure as the > input list, in my example: > > > $I > $I$A > [1] "c" "b" "a" > > $I$B > [1] "f" "e" "d" > > $I$C > [1] "i" "h" "g" > > > $II > $II$A > $II$A$a > [1] "c" "b" "a" > > $II$A$b > [1] "f" "e" "d" > > $II$A$c > [1] "i" "h" "g" > > > $II$B > [1] "f" "e" "d" > > $II$C > [1] "i" "h" "g" > > > > I understand that with a fixed number of recursion levels one can use > lapply() in a nested way, but what if the numbers of recursion levels > is not fixed or is different between the list elements as it is in my > example? > > Any hint will be appreciated. > > Best, > > Georg > > ______________________________________________ > R-help at r-project.org mailing list > 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. >-- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
See ?rapply for your example rapply( test.list, rev, how='replace' ) HTH, Chuck On Wed, 11 Jun 2008, Georg Otto wrote:> > Hi, > > I have a question about applying a function recursively through a > list. Suppose I have a list where the different elements have > different levels of recursion: > > >> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")), > + "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), > + "c"=c("g", "h", "i")), > + "B"=c("d", "e", "f"), "C"=c("g", "h", "i"))) > >> test.list > $I > $I$A > [1] "a" "b" "c" > > $I$B > [1] "d" "e" "f" > > $I$C > [1] "g" "h" "i" > > > $II > $II$A > $II$A$a > [1] "a" "b" "c" > > $II$A$b > [1] "d" "e" "f" > > $II$A$c > [1] "g" "h" "i" > > > $II$B > [1] "d" "e" "f" > > $II$C > [1] "g" "h" "i" > > > > I would like to apply a function recursively to that list, in a way > that the function does someting with each vector (eg. rev()) and > returns a list of modified vectors that has the same structure as the > input list, in my example: > > > $I > $I$A > [1] "c" "b" "a" > > $I$B > [1] "f" "e" "d" > > $I$C > [1] "i" "h" "g" > > > $II > $II$A > $II$A$a > [1] "c" "b" "a" > > $II$A$b > [1] "f" "e" "d" > > $II$A$c > [1] "i" "h" "g" > > > $II$B > [1] "f" "e" "d" > > $II$C > [1] "i" "h" "g" > > > > I understand that with a fixed number of recursion levels one can use > lapply() in a nested way, but what if the numbers of recursion levels > is not fixed or is different between the list elements as it is in my > example? > > Any hint will be appreciated. > > Best, > > Georg > > ______________________________________________ > R-help at r-project.org mailing list > 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. >Charles C. Berry (858) 534-2098 Dept of Family/Preventive Medicine E mailto:cberry at tajo.ucsd.edu UC San Diego http://famprevmed.ucsd.edu/faculty/cberry/ La Jolla, San Diego 92093-0901
on 06/11/2008 10:51 AM Georg Otto wrote:> Hi, > > I have a question about applying a function recursively through a > list. Suppose I have a list where the different elements have > different levels of recursion: > > >> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")), > + "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), > + "c"=c("g", "h", "i")), > + "B"=c("d", "e", "f"), "C"=c("g", "h", "i"))) > >> test.list > $I > $I$A > [1] "a" "b" "c" > > $I$B > [1] "d" "e" "f" > > $I$C > [1] "g" "h" "i" > > > $II > $II$A > $II$A$a > [1] "a" "b" "c" > > $II$A$b > [1] "d" "e" "f" > > $II$A$c > [1] "g" "h" "i" > > > $II$B > [1] "d" "e" "f" > > $II$C > [1] "g" "h" "i" > > > > I would like to apply a function recursively to that list, in a way > that the function does someting with each vector (eg. rev()) and > returns a list of modified vectors that has the same structure as the > input list, in my example: > > > $I > $I$A > [1] "c" "b" "a" > > $I$B > [1] "f" "e" "d" > > $I$C > [1] "i" "h" "g" > > > $II > $II$A > $II$A$a > [1] "c" "b" "a" > > $II$A$b > [1] "f" "e" "d" > > $II$A$c > [1] "i" "h" "g" > > > $II$B > [1] "f" "e" "d" > > $II$C > [1] "i" "h" "g" > > > > I understand that with a fixed number of recursion levels one can use > lapply() in a nested way, but what if the numbers of recursion levels > is not fixed or is different between the list elements as it is in my > example? > > Any hint will be appreciated. > > Best, > > GeorgSee ?rapply, which is a recursive version of lapply(): > rapply(test.list, rev, how = "list") $I $I$A [1] "c" "b" "a" $I$B [1] "f" "e" "d" $I$C [1] "i" "h" "g" $II $II$A $II$A$a [1] "c" "b" "a" $II$A$b [1] "f" "e" "d" $II$A$c [1] "i" "h" "g" $II$B [1] "f" "e" "d" $II$C [1] "i" "h" "g" HTH, Marc Schwartz
Georg Otto wrote:> Hi, > > I have a question about applying a function recursively through a > list. Suppose I have a list where the different elements have > different levels of recursion: > >...> > I understand that with a fixed number of recursion levels one can use > lapply() in a nested way, but what if the numbers of recursion levels > is not fixed or is different between the list elements as it is in my > example? >Hi Georg, Have a look at listBuilder and listCrawler in the crank package. Jim
Hi, thanks a lot for your help. Somehow rapply had escaped my notice. I also have a follow-up question on that. I would like to "flatten" my output list to a list with only one level. Option "unlist" in rapply returns a character vector, in my example:> rapply(test.list, rev, how="unlist")I.A1 I.A2 I.A3 I.B1 I.B2 I.B3 I.C1 I.C2 I.C3 II.A.a1 "c" "b" "a" "f" "e" "d" "i" "h" "g" "c" II.A.a2 II.A.a3 II.A.b1 II.A.b2 II.A.b3 II.A.c1 II.A.c2 II.A.c3 II.B1 II.B2 "b" "a" "f" "e" "d" "i" "h" "g" "f" "e" II.B3 II.C1 II.C2 II.C3 "d" "i" "h" "g" What I rather would like to achieve is a list like this: $I.A [1] "c" "b" "a" $I.B [1] "f" "e" "d" $I.C [1] "i" "h" "g" $II.A.a [1] "c" "b" "a" $II.A.b [1] "f" "e" "d" $II.A.c [1] "i" "h" "g" $II.B [1] "f" "e" "d" $II.C [1] "i" "h" "g" Any hint will be appreciated. Best, Georg Prof Brian Ripley <ripley at stats.ox.ac.uk> writes:> See ?rapply > > On Wed, 11 Jun 2008, Georg Otto wrote: > >> >> Hi, >> >> I have a question about applying a function recursively through a >> list. Suppose I have a list where the different elements have >> different levels of recursion: >> >> >>> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")), >> + "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), >> + "c"=c("g", "h", "i")), >> + "B"=c("d", "e", "f"), "C"=c("g", "h", "i"))) >> >>> test.list >> $I >> $I$A >> [1] "a" "b" "c" >> >> $I$B >> [1] "d" "e" "f" >> >> $I$C >> [1] "g" "h" "i" >> >> >> $II >> $II$A >> $II$A$a >> [1] "a" "b" "c" >> >> $II$A$b >> [1] "d" "e" "f" >> >> $II$A$c >> [1] "g" "h" "i" >> >> >> $II$B >> [1] "d" "e" "f" >> >> $II$C >> [1] "g" "h" "i" >> >> >> >> I would like to apply a function recursively to that list, in a way >> that the function does someting with each vector (eg. rev()) and >> returns a list of modified vectors that has the same structure as the >> input list, in my example: >> >> >> $I >> $I$A >> [1] "c" "b" "a" >> >> $I$B >> [1] "f" "e" "d" >> >> $I$C >> [1] "i" "h" "g" >> >> >> $II >> $II$A >> $II$A$a >> [1] "c" "b" "a" >> >> $II$A$b >> [1] "f" "e" "d" >> >> $II$A$c >> [1] "i" "h" "g" >> >> >> $II$B >> [1] "f" "e" "d" >> >> $II$C >> [1] "i" "h" "g" >> >> >> >> I understand that with a fixed number of recursion levels one can use >> lapply() in a nested way, but what if the numbers of recursion levels >> is not fixed or is different between the list elements as it is in my >> example? >> >> Any hint will be appreciated. >> >> Best, >> >> Georg >> >> ______________________________________________ >> R-help at r-project.org mailing list >> 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. >> > > -- > Brian D. Ripley, ripley at stats.ox.ac.uk > Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ > University of Oxford, Tel: +44 1865 272861 (self) > 1 South Parks Road, +44 1865 272866 (PA) > Oxford OX1 3TG, UK Fax: +44 1865 272595 > > ______________________________________________ > R-help at r-project.org mailing list > 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. >
Prof Brian Ripley wrote: > > See ?rapply Golly, the things one learns when least expecting it. Jim
Wrap each element in an environment, flatten that and then extact the element in each environment. (Be sure not to use an old version of R since sufficiently far back R had a bug when environments were stored in lists that was since fixed.) L <- rapply(test.list, function(el) environment(), how = "unlist") lapply(L, "[[", "el") Alternately use proto objects (http://r-proto.googlecode.com): library(proto) L <- rapply(test.list, function(el) proto(, el = el), how = "unlist") lapply(L, "[[", "el") On Thu, Jun 12, 2008 at 7:11 AM, Georg Otto <georg.otto at tuebingen.mpg.de> wrote:> > Hi, > > thanks a lot for your help. Somehow rapply had escaped my notice. I > also have a follow-up question on that. I would like to "flatten" my > output list to a list with only one level. Option "unlist" in rapply > returns a character vector, in my example: > >> rapply(test.list, rev, how="unlist") > I.A1 I.A2 I.A3 I.B1 I.B2 I.B3 I.C1 I.C2 I.C3 II.A.a1 > "c" "b" "a" "f" "e" "d" "i" "h" "g" "c" > II.A.a2 II.A.a3 II.A.b1 II.A.b2 II.A.b3 II.A.c1 II.A.c2 II.A.c3 II.B1 II.B2 > "b" "a" "f" "e" "d" "i" "h" "g" "f" "e" > II.B3 II.C1 II.C2 II.C3 > "d" "i" "h" "g" > > > What I rather would like to achieve is a list like this: > > > $I.A > [1] "c" "b" "a" > > $I.B > [1] "f" "e" "d" > > $I.C > [1] "i" "h" "g" > > > $II.A.a > [1] "c" "b" "a" > > $II.A.b > [1] "f" "e" "d" > > $II.A.c > [1] "i" "h" "g" > > > $II.B > [1] "f" "e" "d" > > $II.C > [1] "i" "h" "g" > > > Any hint will be appreciated. > > Best, > > Georg > > > > > Prof Brian Ripley <ripley at stats.ox.ac.uk> writes: > >> See ?rapply >> >> On Wed, 11 Jun 2008, Georg Otto wrote: >> >>> >>> Hi, >>> >>> I have a question about applying a function recursively through a >>> list. Suppose I have a list where the different elements have >>> different levels of recursion: >>> >>> >>>> test.list<-list("I"=list("A"=c("a", "b", "c"), "B"=c("d", "e", "f"), "C"=c("g", "h", "i")), >>> + "II"=list("A"=list("a"=c("a", "b", "c"), "b"=c("d", "e", "f"), >>> + "c"=c("g", "h", "i")), >>> + "B"=c("d", "e", "f"), "C"=c("g", "h", "i"))) >>> >>>> test.list >>> $I >>> $I$A >>> [1] "a" "b" "c" >>> >>> $I$B >>> [1] "d" "e" "f" >>> >>> $I$C >>> [1] "g" "h" "i" >>> >>> >>> $II >>> $II$A >>> $II$A$a >>> [1] "a" "b" "c" >>> >>> $II$A$b >>> [1] "d" "e" "f" >>> >>> $II$A$c >>> [1] "g" "h" "i" >>> >>> >>> $II$B >>> [1] "d" "e" "f" >>> >>> $II$C >>> [1] "g" "h" "i" >>> >>> >>> >>> I would like to apply a function recursively to that list, in a way >>> that the function does someting with each vector (eg. rev()) and >>> returns a list of modified vectors that has the same structure as the >>> input list, in my example: >>> >>> >>> $I >>> $I$A >>> [1] "c" "b" "a" >>> >>> $I$B >>> [1] "f" "e" "d" >>> >>> $I$C >>> [1] "i" "h" "g" >>> >>> >>> $II >>> $II$A >>> $II$A$a >>> [1] "c" "b" "a" >>> >>> $II$A$b >>> [1] "f" "e" "d" >>> >>> $II$A$c >>> [1] "i" "h" "g" >>> >>> >>> $II$B >>> [1] "f" "e" "d" >>> >>> $II$C >>> [1] "i" "h" "g" >>> >>> >>> >>> I understand that with a fixed number of recursion levels one can use >>> lapply() in a nested way, but what if the numbers of recursion levels >>> is not fixed or is different between the list elements as it is in my >>> example? >>> >>> Any hint will be appreciated. >>> >>> Best, >>> >>> Georg >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list >>> 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. >>> >> >> -- >> Brian D. Ripley, ripley at stats.ox.ac.uk >> Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ >> University of Oxford, Tel: +44 1865 272861 (self) >> 1 South Parks Road, +44 1865 272866 (PA) >> Oxford OX1 3TG, UK Fax: +44 1865 272595 >> >> ______________________________________________ >> R-help at r-project.org mailing list >> 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. >> > > ______________________________________________ > R-help at r-project.org mailing list > 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. >