Как связать векторы в разные столбцы, оставив НА в оставшихся ячейках

Допустим, у меня есть неопределенное количество векторов разной длины, и я хочу эффективно связать их вместе, с оговоркой, что каждый из них должен занимать отдельный столбец в итоговом кадре data.frame. Вы можете предположить, что векторы содержатся в списке, но вы не можете полагаться на какие-либо имена компонентов, которые могут быть определены в этом списке.

Ниже я представляю случайный образец ввода (lv) и плохое решение для генерации требуемого вывода, которое вручную создает результирующий data.frame путем повторения NA и объединения каждого входного вектора по имени.

set.seed(1);
lv <- list(a=sample(30,5),b=sample(30,3),c=sample(30,7),d=sample(30,2));
lv;
## $a
## [1]  8 11 17 25  6
##
## $b
## [1] 27 28 19
##
## $c
## [1] 19  2  6  5 18 10 30
##
## $d
## [1] 15 21
##
with(lv,data.frame(a=c(a,rep(NA,length(b)+length(c)+length(d))),b=c(rep(NA,length(a)),b,rep(NA,length(c)+length(d))),c=c(rep(NA,length(a)+length(b)),c,rep(NA,length(d))),d=c(rep(NA,length(a)+length(b)+length(c)),d)));
##     a  b  c  d
## 1   8 NA NA NA
## 2  11 NA NA NA
## 3  17 NA NA NA
## 4  25 NA NA NA
## 5   6 NA NA NA
## 6  NA 27 NA NA
## 7  NA 28 NA NA
## 8  NA 19 NA NA
## 9  NA NA 19 NA
## 10 NA NA  2 NA
## 11 NA NA  6 NA
## 12 NA NA  5 NA
## 13 NA NA 18 NA
## 14 NA NA 10 NA
## 15 NA NA 30 NA
## 16 NA NA NA 15
## 17 NA NA NA 21

Примечание: вам не обязательно использовать rbind(), я просто почувствовал, что это самый ясный способ представить проблему. Другой способ думать об этом: я хочу cbind() векторов в разные (никогда не перекрывающиеся) строки.


person bgoldst    schedule 29.04.2015    source источник
comment
Используйте set.seed при представлении случайной выборки, чтобы мы могли ее воспроизвести.   -  person David Arenburg    schedule 29.04.2015
comment
Может ли какое-либо из значений быть 0?   -  person joran    schedule 29.04.2015
comment
@joran, да, их могло быть ноль.   -  person bgoldst    schedule 29.04.2015
comment
Хорошо, я играл с идеей использования функции диагонали блока, такой как Matrix::bdiag, но она заполняется нулями.   -  person joran    schedule 29.04.2015


Ответы (1)


Пытаться

library(reshape2)
library(data.table)
dcast(setDT(melt(lv))[, rn:=.I], rn~L1, value.var='value')

Or

dcast(setDT(melt(lv), keep.rownames=TRUE), 
                  as.numeric(rn)~L1, value.var='value')

Или как предложил @David Arenburg

recast(lv, seq_along(unlist(lv)) ~ L1)

Или используя base R

d1 <- stack(lv)
reshape(transform(d1, rn=1:nrow(d1)), idvar='rn',
                         timevar='ind', direction='wide')
person akrun    schedule 29.04.2015
comment
@dayne Спасибо, пытался избежать reshape2, похоже, мне это нужно. - person akrun; 29.04.2015
comment
Вам не нужен reshape2 в версии для разработчиков. Вы также можете вместо этого сделать rn:= .I. Наконец, я понятия не имею, как это произошло так быстро. - person David Arenburg; 29.04.2015
comment
Ты хозяин, @akrun, это было быстро! Можно ли это сделать в базе R? - person bgoldst; 29.04.2015
comment
@bgoldst Я думаю, что stack с _2 _ / _ 3_ может быть вариантом (не тестировалось). - person akrun; 29.04.2015
comment
@DavidArenburg Я думаю, у setDT тоже есть опция keep.rownames - person akrun; 29.04.2015
comment
Оно делает. Но я не понимаю, что ты пытаешься сказать - person David Arenburg; 29.04.2015
comment
dcast(setDT(melt(lv), keep.rownames=TRUE), as.numeric(rn)~L1, value.var='value') Да, seq( подход немного компактнее, - person akrun; 29.04.2015