Объединение списков разной длины в кадр данных

У меня есть данные, такие как SampleData ниже, у которых есть списки различной длины, которые я хотел бы объединить во фрейм данных, как желаемый результат ниже. Я попытался использовать lapply и cbind.na из пакета qpcR, как в примере ниже, но по какой-то причине он не позволяет мне превратить результат в кадр данных. Если я просто использовал два списка и cbind.na, он объединит их и добавит NA к концу, как я хочу, но когда я пытаюсь использовать его в lapply, он просто оставляет их как список списков разной длины. Любые советы с благодарностью.

SampleData<-list(list(1,2,3),list(1,2),list(3,4,6,7))

Desired Result:
structure(list(V1 = c(1, 2, 3, NA), V2 = c(1, 2, NA, NA), V3 = c(3, 
4, 6, 7)), .Names = c("V1", "V2", "V3"), row.names = c(NA, -4L
), class = "data.frame")


Example Code:

lapply(SampleData,qpcR:::cbind.na)

2 ответа

Решение

Мой первый инстинкт просмотра ваших данных заключается в том, что, используя data.frameВы неявно заявляете, что элементы в ряду являются парными. То есть, в вашем примере, "3" $V1 и "6" из $V3 предназначены для связи друг с другом. (Если вы посмотрите на mtcars, каждый столбец первого ряда связан непосредственно и исключительно с "Mazda RX4".) Если это не так, то деформируйте их в data.frame как будто это неправильно представляет ваши данные и нравится поощрять неправильный анализ / предположения.

Предполагая, что они на самом деле "спарены", мой следующий инстинкт - попробовать что-то вроде do.call(cbind, SampleData), но это предоставляет переработанные данные, а не то, что вы хотите. Итак, хитрость для сдерживания рециркуляции состоит в том, чтобы заставить их быть одинаковой длины.

maxlen <- max(lengths(SampleData))
SampleData2 <- lapply(SampleData, function(lst) c(lst, rep(NA, maxlen - length(lst))))

Мы можем сначала переименовать:

names(SampleData2) <- paste("V", seq_along(SampleData2), sep = "")

Поскольку данные кажутся однородными (и должно быть, если вы намереваетесь поместить каждый элемент в виде столбца data.frame), полезно снять список:

SampleData3 <- lapply(SampleData2, unlist)

Тогда это так же просто, как:

as.data.frame(SampleData3)
#   V1 V2 V3
# 1  1  1  3
# 2  2  2  4
# 3  3 NA  6
# 4 NA NA  7

Вот модифицированная версия с length<- назначение

setNames(do.call(cbind.data.frame, lapply(lapply(SampleData, unlist), 
        `length<-`, max(lengths(SampleData)))), paste0("V", 1:3))
#  V1 V2 V3
#1  1  1  3
#2  2  2  4
#3  3 NA  6
#4 NA NA  7
Другие вопросы по тегам