[R] substitute "x" for "pattern" in a list, while preservign list "structure". lapply, gsub, list...?

Marc Schwartz marc_schwartz at comcast.net
Wed May 16 19:35:01 CEST 2007


On Wed, 2007-05-16 at 13:18 -0400, Gabor Grothendieck wrote:
> On 5/16/07, Marc Schwartz <marc_schwartz at comcast.net> wrote:
> > On Wed, 2007-05-16 at 09:25 -0700, new ruser wrote:
> > > I am experimenting with some of the common r functions.
> > > I had a question re:using "gsub" (or some similar functions) on the
> > > contents of a list.
> > >
> > > I want to design a function that looks at "everything" contained din a
> > > list, and anytime it finds the text string "pattern" replace it with
> > > "x".  I also wish to preserve the "structure" of the original list.
> > > What is a good way to accomplish this?
> > >
> > > I tried :
> > >
> > > a = matrix(data=c(23,45,'red',78),nrow=2)
> > > b = c('red','green',1,2,3)
> > > d = data.frame( test1=c(223,445,'red',78,56) , test2=
> > > c('red',NA,NA,NA,NA) )
> > > e= list(a,b,d)
> > > list1 = list(a,b,d,e)
> > >
> > > list2 = lapply(list1,function(list)(gsub("red","green",list)))
> > >
> > > str(list1)
> > > str(list2)
> > >
> > > but the structue fo the list changed.
> >
> > I suspect that you will need to use rapply(), which is a recursive
> > version of lapply().
> >
> > For example:
> >
> > > str(list1)
> > List of 4
> >  $ : chr [1:2, 1:2] "23" "45" "red" "78"
> >  $ : chr [1:5] "red" "green" "1" "2" ...
> >  $ :'data.frame':       5 obs. of  2 variables:
> >  ..$ test1: Factor w/ 5 levels "223","445","56",..: 1 2 5 4 3
> >  ..$ test2: Factor w/ 1 level "red": 1 NA NA NA NA
> >  $ :List of 3
> >  ..$ : chr [1:2, 1:2] "23" "45" "red" "78"
> >  ..$ : chr [1:5] "red" "green" "1" "2" ...
> >  ..$ :'data.frame':    5 obs. of  2 variables:
> >  .. ..$ test1: Factor w/ 5 levels "223","445","56",..: 1 2 5 4 3
> >  .. ..$ test2: Factor w/ 1 level "red": 1 NA NA NA NA
> >
> >
> >
> > list3 <- rapply(list1, function(x) gsub("red", "green", x),
> >                how = "replace")
> >
> > > str(list3)
> > List of 4
> >  $ : chr [1:2, 1:2] "23" "45" "green" "78"
> >  $ : chr [1:5] "green" "green" "1" "2" ...
> >  $ :List of 2
> >  ..$ test1: chr [1:5] "223" "445" "green" "78" ...
> >  ..$ test2: chr [1:5] "green" NA NA NA ...
> >  $ :List of 3
> >  ..$ : chr [1:2, 1:2] "23" "45" "green" "78"
> >  ..$ : chr [1:5] "green" "green" "1" "2" ...
> >  ..$ :List of 2
> >  .. ..$ test1: chr [1:5] "223" "445" "green" "78" ...
> >  .. ..$ test2: chr [1:5] "green" NA NA NA ...
> >
> >
> > Note however, the impact of using gsub(), which is that factors are
> > coerced to characters. So consider what you want the end game to be.
> >
> > See ?rapply for more information.
> >
> 
> Also note that from your str's above it appears that data.frames do not
> survive rapply but rather are changed to plain lists.  I don't know whether
> that is intentional on the part of the developers or not.

Right, which I noted and would be consistent with the behavior of
lapply() on data frames, which also simplifies the result to a normal
list.

Since rapply() is documented to be recursive version of lapply(), the
result above would be expected, at least implicitly.

Thanks for raising the point Gabor.

Regards,

Marc



More information about the R-help mailing list