如何从R中的统一列表中提取值?

时间:2020-12-16 21:24:13

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?

是否有相当于Python列表的理解或具有相同效果的东西?

4 个解决方案

#1


15  

You can use sapply:

你可以使用sapply:

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

#2


6  

Given the data structure you provided, I would use sapply:

鉴于您提供的数据结构,我会使用sapply:

sapply(people, function(x) x[2])

> sapply(people, function(x) x[2])
 age  age  age  age  age 
"23" "35" "20" "31" "26" 

However, you'll notice that the results of this are character data.

但是,您会注意到这些结果是字符数据。

> class(people[[1]])
[1] "character"

One approach would be to coerce to as.numeric() or as.integer() in the call to sapply.

一种方法是在对sapply的调用中强制使用as.numeric()或as.integer()。

Alternatively - if you have flexibility over how you store the data in the first place, it may make sense to store it as a list of data.frames:

或者 - 如果您首先可以灵活地存储数据,那么将它存储为data.frames列表可能是有意义的:

people = vector("list", 5)
people[[1]] = data.frame(name="Paul", age=23)
people[[2]] = data.frame(name="Peter", age=35)
...

If you are going to go that far, you may also want to consider a single data.frame for all of your data:

如果您要走得那么远,您可能还需要考虑所有数据的单个data.frame:

people2 <- data.frame(name = c("Paul", "Peter", "Sam", "Lyle", "Fred")
                      , age = c(23,35,20,31, 26))

There may be some other reason why you didn't consider this approach the first time around though...

可能还有其他一些原因导致您第一次没有考虑这种方法...

#3


1  

ages <- sapply(1:length(people), function(i) as.numeric(people[[i]][[2]]))
ages

Output:

输出:

[1] 23 35 20 31 26

[1] 23 35 20 31 26

#4


0  

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

除了申请家庭之外,还有@Hadley的purrr软件包,它为这类工作提供了map_-functions功能。

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

(例如,这里讨论的申请家庭存在一些差异。)

OPs example:

OPs示例:

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

#1


15  

You can use sapply:

你可以使用sapply:

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

#2


6  

Given the data structure you provided, I would use sapply:

鉴于您提供的数据结构,我会使用sapply:

sapply(people, function(x) x[2])

> sapply(people, function(x) x[2])
 age  age  age  age  age 
"23" "35" "20" "31" "26" 

However, you'll notice that the results of this are character data.

但是,您会注意到这些结果是字符数据。

> class(people[[1]])
[1] "character"

One approach would be to coerce to as.numeric() or as.integer() in the call to sapply.

一种方法是在对sapply的调用中强制使用as.numeric()或as.integer()。

Alternatively - if you have flexibility over how you store the data in the first place, it may make sense to store it as a list of data.frames:

或者 - 如果您首先可以灵活地存储数据,那么将它存储为data.frames列表可能是有意义的:

people = vector("list", 5)
people[[1]] = data.frame(name="Paul", age=23)
people[[2]] = data.frame(name="Peter", age=35)
...

If you are going to go that far, you may also want to consider a single data.frame for all of your data:

如果您要走得那么远,您可能还需要考虑所有数据的单个data.frame:

people2 <- data.frame(name = c("Paul", "Peter", "Sam", "Lyle", "Fred")
                      , age = c(23,35,20,31, 26))

There may be some other reason why you didn't consider this approach the first time around though...

可能还有其他一些原因导致您第一次没有考虑这种方法...

#3


1  

ages <- sapply(1:length(people), function(i) as.numeric(people[[i]][[2]]))
ages

Output:

输出:

[1] 23 35 20 31 26

[1] 23 35 20 31 26

#4


0  

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

除了申请家庭之外,还有@Hadley的purrr软件包,它为这类工作提供了map_-functions功能。

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

(例如,这里讨论的申请家庭存在一些差异。)

OPs example:

OPs示例:

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