Преобразование данного списка в dataframe - PullRequest
0 голосов
/ 10 января 2012

У меня есть следующий список:

$id1
$id1[[1]]
         A              B               
        "A"            "B"                
$id1[[2]]
         A             B 
        "A"           "A1" 
$id2
$id2[[1]]
         A              B               
        "A2"           "B2" 

В виде R-pastable:

dat = structure(list(SampleTable = structure(list(id2 = list(structure(c("90", "7"), .Names = c("T", "G")), structure(c("90", "8"), .Names = c("T", "G"))), id1 = structure(c("1", "1"), .Names = c("T", "G"))), .Names = c("id2", "id1"))), .Names = "SampleTable") 

Я хочу преобразовать данный список в следующий фрейм данных:

id1   A    B
id1   A    A1 
id2   A2   B2 

Ответы [ 3 ]

5 голосов
/ 10 января 2012

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

Это можно сделать напрямую с помощью do.call, lapply и rbind, но это не очень удобно для чтения, даже если вы знакомы с этими функциями.

# Sample data 
d <- list(
  id1 = list(
    data.frame( x=1, y=1 ),
    data.frame( x=2, y=2 )
  ),
  id2 = list(
    data.frame( x=3, y=3 ),
    data.frame( x=4, y=4 )
  ),
  id3 = list(
    data.frame( x=5, y=5 ),
    data.frame( x=6, y=6 )
  )
)

# Convert
d <- data.frame(
  id=rep(names(d), unlist(lapply(d,length))),
  do.call( rbind, lapply(d, function(u) do.call(rbind, u)) )
)

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

d <- structure(list(SampleTable = structure(list(id2 = list(structure(c("90", "7"), .Names = c("T", "G")), structure(c("90", "8"), .Names = c("T", "G"))), id1 = structure(c("1", "1"), .Names = c("T", "G"))), .Names = c("id2", "id1"))), .Names = "SampleTable") 
result <- list()
for(i in seq_along(d$SampleTable)) {
  id <- names(d$SampleTable)[i]
  block <- d$SampleTable[[i]]
  if(is.atomic(block)) {
    block <- list(block)
  }
  for(row in block) {
    result <- c(result, list(data.frame(id, as.data.frame(t(row)))))
  }    
}
result <- do.call(rbind, result)
1 голос
/ 10 января 2012

Примечание!Я не мог получить расплавление и отливку, работая с подобными неровными данными (я пытался больше часа ...) Я собираюсь оставить этот ответ здесь, чтобы показать, что для такого рода операций можно также использовать изменение формы pacakge.

Используя пример данных vincent, вы можете использовать melt и cast из пакета изменения формы:

library(reshape)
res = cast(melt(d))[-1]
names(res) = c("id","x","y")
res
   id x y
1 id1 1 1
2 id2 3 3
3 id3 5 5
4 id1 2 2
5 id2 4 4
6 id3 6 6

Порядок в результирующем data.frame не тот же, но результатидентичны.И код немного короче.Я использую [-1], чтобы удалить первый столбец, который также возвращается melt.Эта дополнительная переменная является индексом столбца отдельных data.frames в списке списков.Просто посмотрите на результат melt(d), который, надеюсь, сделает его более понятным.

0 голосов
/ 10 января 2012

Это немного грязно, что вы позволяете. Этот dat объект имеет дополнительный «слой» над ним, поэтому с ним проще работать dat[[1]]:

dfrm <- data.frame(dat[[1]], stringsAsFactors=FALSE)
names(dfrm) <- sub("\\..+$", "", names(dfrm))

> dfrm
  id2 id2 id1
T  90  90   1
G   7   8   1
> t(dfrm)
    T    G  
id2 "90" "7"
id2 "90" "8"
id1 "1"  "1"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...