Как извлечь значения из единого списка в R? - PullRequest
10 голосов
/ 02 августа 2011

Например, как я могу получить вектор возраста каждого человека в списке people ниже:

> 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

Есть ли эквивалент понимания списка Python или что-то подобное?

Ответы [ 5 ]

17 голосов
/ 02 августа 2011

Вы можете использовать sapply :

> sapply(people, function(x){as.numeric(x[2])})
[1] 23 35 20 31 26
7 голосов
/ 02 августа 2011

Учитывая предоставленную вами структуру данных, я бы использовал sapply:

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

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

Однако вы заметите, что результатом этого являются символьные данные.

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

Один из подходов заключается в принуждении к as.numeric() или as.integer() в вызове sapply.

В качестве альтернативы - если у вас есть гибкость в том, как вы храните данные в первомместо, возможно, имеет смысл сохранить его в виде списка data.frame s:

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

Если вы собираетесь зайти так далеко, вы можете также рассмотреть вопрос об одном data.frame для всехваши данные:

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

Может быть, есть и другая причина, почему вы не рассматривали этот подход в первый раз, хотя ...

1 голос
/ 04 марта 2017
ages <- sapply(1:length(people), function(i) as.numeric(people[[i]][[2]]))
ages

Вывод:

[1] 23 35 20 31 26

0 голосов
/ 29 декабря 2018

Хотя этот вопрос довольно старый, я хотел бы поделиться своим подходом к этому.Конечно, можно сделать с sapply, как предложено tflutre .Но я нахожу это более интуитивно понятным с помощью функции unlist:

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

ПРИМЕЧАНИЕ. При умножении на two в 2 * length(people) в * хранятся два элемента poeple список.Это можно сделать более общим, написав length(people[[1]]) * length(people)

Здесь unlist(people, use.names = F) дает

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

, и мы разрезаем это на каждый другой элемент, используя команду seq.

0 голосов
/ 29 января 2018

В дополнение к apply -семейству существует пакет purrr @ 1004 * @ Hadley, который предлагает map_ -функции для такого рода работы.

(Есть несколько различий с apply -семейством, обсуждаемым, например, здесь .)

Пример OP:

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)

Подход sapply:

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

И map подход:

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

Конечно, они идентичны:

identical(ages_sapply, ages_map)
[1] TRUE
...