How do I extract values from uniform list in R?

Viewed 32197

For example, how do I get a vector of each and every person's age in the list people below:

> people = vector("list", 5)
> people[[1]] = c(name="Paul", age=23)
> people[[2]] = c(name="Peter", age=35)
> people[[3]] = c(name="Sam", age=20)
> people[[4]] = c(name="Lyle", age=31)
> people[[5]] = c(name="Fred", age=26)
> ages = ???
> ages
[1] 23 35 20 31 26

Is there an equivalent of a Python list comprehension or something to the same effect?

5 Answers

Alternatively to the apply-family there's @Hadley's purrr package which offers the map_-functions for this kind of job.

(There's a few differences to the apply-family discussed for example here.)

OPs example:

people = vector("list", 5)
people[[1]] = c(name="Paul", age=23)
people[[2]] = c(name="Peter", age=35)
people[[3]] = c(name="Sam", age=20)
people[[4]] = c(name="Lyle", age=31)
people[[5]] = c(name="Fred", age=26)

The sapply approach:

ages_sapply <- sapply(people, function(x){as.numeric(x[2])})
print(ages_sapply)
[1] 23 35 20 31 26

And the map approach:

ages_map <- purrr::map_dbl(people, function(x){as.numeric(x[2])})
print(ages_map)
[1] 23 35 20 31 26

Of course they are identical:

identical(ages_sapply, ages_map)
[1] TRUE

Though this question is pretty old, I'd like to share my approach to this. It is certainly possible to do with the sapply as tflutre suggested. But I find it more intuitive by using the unlist function:

> ages <- unlist(people, use.names = F)[seq(2, 2 * length(people), 2)]
> ages
[1] "23" "35" "20" "31" "26"

NOTE the multiplication by two in 2 * length(people), there are two elements stored in the poeple list. This can be made more generic by writing length(people[[1]]) * length(people)

Here unlist(people, use.names = F) yields

[1] "Paul"  "23"    "Peter" "35"    "Sam"   "20"    "Lyle"  "31"    "Fred" 
[10] "26" 

and we slice that by every other element using seq command.

Related