Hi, I'm trying to subset a list which contains variable length vectors. What I want to do is extract (eg.) the 3rd item in each vector (with length >= 3). At the moment I'm using sapply(list.of.vectors, function(x) {x[3]}). The problem with this is that sapply returns a list of the same length of list.of.vectors so I end up with a whole lot of null entries from those vectors that aren't long enough. I have a similar problem if I want to select all the vectors where the 3rd item is a specified value. Does anyone have any better solutions? Thanks for you help, Hadley
When I did it in S-Plus 6.1 and R 1.8.0, I didn't get NULL entries: I got NAs. There is a difference between NULLs and NAs. The NAs can be deleted using is.na, as follows: > list.of.vectors <- list(a=1, b=1:3) > x3 <- sapply(list.of.vectors, function(x)x[3]) > x3 a b NA 3 > x3 a b NA 3 > x3[!is.na(x3)] b 3 > Is this acceptable? spencer graves Hadley Wickham wrote:> Hi, > > I'm trying to subset a list which contains variable length vectors. > What I want to do is extract (eg.) the 3rd item in each vector (with > length >= 3). At the moment I'm using sapply(list.of.vectors, > function(x) {x[3]}). The problem with this is that sapply returns a > list of the same length of list.of.vectors so I end up with a whole > lot of null entries from those vectors that aren't long enough. I > have a similar problem if I want to select all the vectors where the > 3rd item is a specified value. > > Does anyone have any better solutions? > > Thanks for you help, > > Hadley > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://www.stat.math.ethz.ch/mailman/listinfo/r-help
This has already been answered but I think behind your question may have been the thought of whether its possible to do it all at once: transformation and selection. There are languages that do allow this. For example, Python has list comprehensions which are things like this: # give me the squares of the even numbers from 1-10, in a list. >>> [ x*x for x in range(1,11) if x%2 == 0] In R you could do this: sapply( 1:10, function(x)x^2 ) but AFAIK you can't incorporate the condition without creating a temporary: t <- sapply( 1:10, function(x)x^2 ) z <- t[ t%%2 == 0 ] (In this simple example we could have used the fact that parity is invariant under squaring to reduce 1:10 to seq(2,10,2) and thereby eliminate the selection part but that's not really the point since that avoids the problem rather than allowing its expression in the terms we want.) --- Date: Mon, 10 Nov 2003 13:43:07 +1300 From: Hadley Wickham <h.wickham at auckland.ac.nz> To: R-Help Mailing List <r-help at stat.math.ethz.ch> Subject: [R] Subsetting a list of vectors Hi, I'm trying to subset a list which contains variable length vectors. What I want to do is extract (eg.) the 3rd item in each vector (with length >= 3). At the moment I'm using sapply(list.of.vectors, function(x) {x[3]}). The problem with this is that sapply returns a list of the same length of list.of.vectors so I end up with a whole lot of null entries from those vectors that aren't long enough. I have a similar problem if I want to select all the vectors where the 3rd item is a specified value. Does anyone have any better solutions? Thanks for you help, Hadley
Dirk and Ray have provided two very clever solutions which perform transformation and selection in one go by returning NA and NULL respectively for unwanted elements and then eliminating the NAs and NULLs. I thought it would be worthwhile to bring them together and make some further minor improvements. Note that for the NULL solution we use the fact that if(FALSE)... with no else leg equals NULL. Problem 1. If v is a list of vectors, get the vector which is the third element of each vector in v. Do not include any elements for vectors with less than 3 elements. Here the NA solution is particularly short: as.numeric( na.omit( sapply( v, "[", 3 ) ) ) but the NULL solution seems closer to the list comprehension idea: unlist( sapply( v, function(x) if (length(x)>=3) x[3] ) ) Problem 2. Express this Python program in R: # give me the squares of the even numbers from 1-10, in a list. >>> [ x*x for x in range(1,11) if x%2 == 0] Here the NULL Solution is both short and closer to the Python one: unlist( sapply( 1:10, function(x) if (x%%2==0) x^2 ) ) while the NA solution is: as.numeric(na.omit(sapply(1:10,function(x)if(x%%2==0)x^2 else NA)))
Hi, I propose here a solution that relies on names of elements: # From a list, with any names ll=list(v1=1:4,v2=1:2,v3=5:7,v4=9:11,v5=1,v6=rnorm(4)) # Make a copy to be able to change names ll2=ll names(ll2)=rep("a",lengh(ll2)) # Use unlist, which "autobuilds" names based on # previous names and indexes in # vectors. # Extracts 3 elements when they exists unlist(ll2)[substring(names(unlist(ll2)),2)=="3"] Eric At 13:43 10/11/2003 +1300, Hadley Wickham wrote:>Hi, > >I'm trying to subset a list which contains variable length vectors. >What I want to do is extract (eg.) the 3rd item in each vector (with >length >= 3). At the moment I'm using sapply(list.of.vectors, function(x) >{x[3]}). The problem with this is that sapply returns a list of the same >length of list.of.vectors so I end up with a whole lot of null entries >from those vectors that aren't long enough. I have a similar problem if I >want to select all the vectors where the 3rd item is a specified value. > >Does anyone have any better solutions? > >Thanks for you help, > >Hadley-------------------------------------------------- L'erreur est certes humaine, mais un vrai d?sastre n?cessite un ou deux ordinateurs. Citation anonyme -------------------------------------------------- Eric Lecoutre Informaticien/Statisticien Institut de Statistique / UCL TEL (+32)(0)10473050 lecoutre at stat.ucl.ac.be URL http://www.stat.ucl.ac.be/ISpersonnel/lecoutre
One idea. If sapply were to have an rm= parameter then the 4 solutions below would reduce to: sapply( v, "[", 3, rm=NA ) sapply( v, function(x) if (length(x)>=3) x[3], rm=NULL ) sapply( 1:10, function(x) if (x%%2==0) x^2, rm=NULL ) sapply( 1:10, function(x) if(x%%2==0)x^2 else NA, rm=NA ) --- Date: Mon, 10 Nov 2003 00:23:17 -0500 (EST) From: Gabor Grothendieck <ggrothendieck at myway.com> To: <edd at debian.org>, <ray at mcs.vuw.ac.nz>, <h.wickham at auckland.ac.nz> Cc: <r-help at stat.math.ethz.ch> Subject: Re: [R] Subsetting a list of vectors Dirk and Ray have provided two very clever solutions which perform transformation and selection in one go by returning NA and NULL respectively for unwanted elements and then eliminating the NAs and NULLs. I thought it would be worthwhile to bring them together and make some further minor improvements. Note that for the NULL solution we use the fact that if(FALSE)... with no else leg equals NULL. Problem 1. If v is a list of vectors, get the vector which is the third element of each vector in v. Do not include any elements for vectors with less than 3 elements. Here the NA solution is particularly short: as.numeric( na.omit( sapply( v, "[", 3 ) ) ) but the NULL solution seems closer to the list comprehension idea: unlist( sapply( v, function(x) if (length(x)>=3) x[3] ) ) Problem 2. Express this Python program in R: # give me the squares of the even numbers from 1-10, in a list.>>> [ x*x for x in range(1,11) if x%2 == 0]Here the NULL Solution is both short and closer to the Python one: unlist( sapply( 1:10, function(x) if (x%%2==0) x^2 ) ) while the NA solution is: as.numeric(na.omit(sapply(1:10,function(x)if(x%%2==0)x^2 else NA))) --- On Mon 11/10, Gabor Grothendieck < ggrothendieck at myway.com > wrote: From: Gabor Grothendieck [mailto: ggrothendieck at myway.com] To: edd at debian.org, ray at mcs.vuw.ac.nz, h.wickham at auckland.ac.nz Cc: r-help at stat.math.ethz.ch Date: Mon, 10 Nov 2003 00:23:17 -0500 (EST) Subject: Re: [R] Subsetting a list of vectors <br><br>Dirk and Ray have provided two very clever solutions which <br>perform transformation and selection in one go <br>by returning NA and NULL respectively for unwanted elements <br>and then eliminating the NAs and NULLs. <br><br>I thought it would be worthwhile to bring them together and <br>make some further minor improvements.<br><br>Note that for the NULL solution we use the fact that <br>if(FALSE)... with no else leg equals NULL.<br><br><br>Problem 1. If v is a list of vectors, get the vector which is the<br>third element of each vector in v. Do not include any elements <br>for vectors with less than 3 elements.<br><br>Here the NA solution is particularly short:<br><br> as.numeric( na.omit( sapply( v, "[", 3 ) ) ) <br><br>but the NULL solution seems closer to the list comprehension idea:<br><br> unlist( sapply( v, function(x) if (length(x)>=3) x[3] ) )<br><br><br>Problem 2. Express this Python program in R:<br> # give me the squares of the even numbers from 1-10, in a list. <br> >>> [ x*x for x in range(1,11) if x%2 == 0]<br><br><br>Here the NULL Solution is both short and closer to the Python one:<br><br> unlist( sapply( 1:10, function(x) if (x%%2==0) x^2 ) )<br><br>while the NA solution is:<br><br> as.numeric(na.omit(sapply(1:10,function(x)if(x%%2==0)x^2 else NA)))<br><br>______________________________________________<br>R-help at stat.math.ethz.ch mailing list<br>https://www.stat.math.ethz.ch/mailman/listinfo/r-help<br>