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

Gabor Grothendieck ggrothendieck at gmail.com
Wed May 16 19:18:56 CEST 2007


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.



More information about the R-help mailing list