2013-02-12 3 views
4

У меня есть список, в котором каждый элемент списка содержит другой список с несколькими объектами имен. Каждый из этих названных объектов представляет собой вектор той же длины. Моя цель - эффективно объединить связанные объекты (одноименные) в матрицу путем конкатенирования векторов.Связанные с объединением вложенные векторы элементов вложенных элементов в матрицы

Вот пример типа структуры, с которой я работаю. Однако в текущем приложении он поступает из mclapply, так как это параллельная многоуровневая модель, и я не думаю, что есть способ получить список списков.

> test=lapply(1:2,function(x){out = list(); out$t=rnorm(3)+x; out$p =rnorm(3)+ x+.1; return(out)}) 
> test 
[[1]] 
[[1]]$t 
[1] 0.5950165 0.8827352 0.5614947 

[[1]]$p 
[1] 2.6144102 1.9688743 0.6241944 


[[2]] 
[[2]]$t 
[1] 2.562030 1.832571 3.018756 

[[2]]$p 
[1] 1.7431969 0.5305784 2.6935106 

Вот грубый способ сделать то, что я хочу

> t.matrix = cbind(test[[1]]$t,test[[2]]$t) 
> t.matrix 
      [,1]  [,2] 
[1,] 2.2094525 2.634907 
[2,] -0.2822453 2.440666 
[3,] 1.1704518 2.483424 

, но вместо этого я хотел бы быть в состоянии сделать это для очень длинного списка (около 1 млн элементов), и мой текущий решение не масштабируется.

Я полагаю, что я мог бы использовать цикл for, но кажется, что должен быть лучший способ сделать это с умным использованием сокращения или unlist или sapply или что-то в этом роде.

+1

Это всегда приятно, когда вы передаете эти виды вопросов использовать 'set.seed()', чтобы мы могли сравнить полученный результат с тем, что вы намереваетесь получить. – A5C1D2H2I1M1N2O1R2T1

+0

Спасибо за указатель! Я обязательно сделаю это в будущем. –

ответ

5
test <- lapply(1:4, function(x) { 
      out = list(); out$t=rnorm(3)+x; out$p =rnorm(3)+ x+.1; return(out)}) 

do.call(cbind, lapply(test, function(X) X[["t"]])) 
## do.call(cbind, lapply(test, "[[", "t"))   ## Or, equivalently 
#   [,1]  [,2]  [,3]  [,4] 
# [1,] 0.7382887 0.9248296 4.205222 5.847823 
# [2,] 3.69 3.6806652 3.324739 3.695195 
# [3,] 2.3611483 1.9305901 1.574586 4.287534 

Или обрабатывать оба набора элементов списка сразу:

elems <- c("t", "p") 
sapply(elems, function(E) { 
    do.call(cbind, 
      lapply(test, function(X) { 
       X[[E]] 
      })) 
}, simplify=FALSE) 
# $t 
#   [,1]  [,2]  [,3]  [,4] 
# [1,] 1.9226614 0.66463844 2.558517 2.743381 
# [2,] 3.0026400 0.03238983 2.195404 3.824127 
# [3,] 0.9371057 3.54638107 2.968717 2.434471 
# 
# $p 
#   [,1]  [,2]  [,3]  [,4] 
# [1,] 0.8544413 2.942780 4.693698 4.158212 
# [2,] 0.7172070 2.381438 4.869630 3.503361 
# [3,] 3.1369674 2.464447 2.484968 3.626174 
3

Что об использовании unlist(test, recursive = FALSE). Это нужно сделать более чем на один шаг, хотя, если вы хотите, чтобы «p» и «t» были отдельными. Вот они вместе:

temp <- do.call(cbind, unlist(test, recursive = FALSE)) 
temp 
      t   p  t  p 
[1,] 0.3735462 2.6952808 2.487429 1.794612 
[2,] 1.1836433 1.4295078 2.738325 3.611781 
[3,] 0.1643714 0.2795316 2.575781 2.489843 

Разделяя их довольно проста:

temp[, colnames(temp) %in% "t"] 
#    t  t 
# [1,] 0.3735462 2.487429 
# [2,] 1.1836433 2.738325 
# [3,] 0.1643714 2.575781 
temp[, colnames(temp) %in% "p"] 
#    p  p 
# [1,] 2.6952808 1.794612 
# [2,] 1.4295078 3.611781 
# [3,] 0.2795316 2.489843 

Вот данные, которые я использовал:

set.seed(1) 
test <- lapply(1:2, function(x) { 
    out = list() 
    out$t=rnorm(3)+x 
    out$p =rnorm(3)+ x+.1 
    return(out) 
}) 
+0

Спасибо за ответ, возвыситесь для вас. Тем не менее, одна из нерешительности у меня с unlist заключается в том, что бенчмаркинг, который я видел [здесь] (http://stackoverflow.com/a/4013388/288545), указывает, что использование списка с включенными именами намного медленнее. Я полагаю, я мог бы использовать ваше решение и отключить флаг useNames, но это сделало бы реконструкцию немного сложнее. –

+0

@ DanielKessler, Спасибо, что поделились этой ссылкой. Я понятия не имел, что сохранение имен при использовании unlist делает функцию намного медленнее! Я предполагаю, что обходной путь, если вы знаете, что ваши данные хорошо организованы, состоят в том, чтобы выбрать столбцы с нечетными номерами и столбцы с четными номерами в конце, но это может быть подвержено ошибкам. Я думаю, что подход Джоша определенно наиболее уместен. – A5C1D2H2I1M1N2O1R2T1

Смежные вопросы