Как преобразовать список списка в аккуратный тиббл или data.frame в R

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

my_lol <- structure(list(coolfactor_score = list(structure(c(0.164477631065473, 
0.198253819406019, 0.396414447052519, 0.133118603987442, 0.107735498488546
), .Names = c("B", "Mac", "NK", "Neu", "Stro")), structure(c(0.186215537135912, 
0.18408529174803, 0.375349920115798, 0.247664923324821, 0.006684327675438
), .Names = c("B", "Mac", "NK", "Neu", "Stro"))), sr_crt = list(
    structure(list(crt = 0.133118603987442, sr = 0.407076876403305), .Names = c("crt", 
    "sr")), structure(list(crt = 0.18408529174803, sr = 0.0829181742326453), .Names = c("crt", 
    "sr"))), sample_names = c("Sample1", "Sample2")), .Names = c("coolfactor_score", 
"sr_crt", "sample_names"))

Это выглядит так:

> my_lol
$coolfactor_score
$coolfactor_score[[1]]
        B       Mac        NK       Neu      Stro 
0.1644776 0.1982538 0.3964144 0.1331186 0.1077355 

$coolfactor_score[[2]]
          B         Mac          NK         Neu        Stro 
0.186215537 0.184085292 0.375349920 0.247664923 0.006684328 


$sr_crt
$sr_crt[[1]]
$sr_crt[[1]]$crt
[1] 0.1331186

$sr_crt[[1]]$sr
[1] 0.4070769


$sr_crt[[2]]
$sr_crt[[2]]$crt
[1] 0.1840853

$sr_crt[[2]]$sr
[1] 0.08291817



$sample_names
[1] "Sample1" "Sample2"
# Note that the number of samples can be more than 2 and cell type more than 5.

Как мне убрать его в этот фрейм данных (тибблы)

CellType    Sample    CoolFactorScore  SR            CRT
B           Sample1   0.1644776        0.4070769     0.1331186
Mac         Sample1   0.1982538        0.4070769     0.1331186
NK          Sample1   0.3964144        0.4070769     0.1331186
Neu         Sample1   0.1331186        0.4070769     0.1331186
Stro        Sample1   0.1077355        0.4070769     0.1331186
B           Sample2   0.186215537      0.08291817    0.1840853
Mac         Sample2   0.184085292      0.08291817    0.1840853
NK          Sample2   0.375349920      0.08291817    0.1840853
Neu         Sample2   0.247664923      0.08291817    0.1840853
Stro        Sample2   0.006684328      0.08291817    0.1840853

person neversaint    schedule 03.05.2017    source источник


Ответы (3)


Один из способов использования базы R:

mylist <- lapply(1:2, function(i) {
  #this is the important bit where you extract the corresponding elements
  #of sample 1 first and sample 2 second.
  df <- data.frame(lapply(my_lol, '[', i))
  names(df) <- c('CoolFactorScore', 'CRT', 'SR', 'Sample')
  df$CellType <- rownames(df)
  row.names(df) <- NULL
  df
})

do.call(rbind, mylist)

Из:

  CoolFactorScore       CRT         SR  Sample CellType
1      0.164477631 0.1331186 0.40707688 Sample1        B
2      0.198253819 0.1331186 0.40707688 Sample1      Mac
3      0.396414447 0.1331186 0.40707688 Sample1       NK
4      0.133118604 0.1331186 0.40707688 Sample1      Neu
5      0.107735498 0.1331186 0.40707688 Sample1     Stro
6      0.186215537 0.1840853 0.08291817 Sample2        B
7      0.184085292 0.1840853 0.08291817 Sample2      Mac
8      0.375349920 0.1840853 0.08291817 Sample2       NK
9      0.247664923 0.1840853 0.08291817 Sample2      Neu
10     0.006684328 0.1840853 0.08291817 Sample2     Stro
person LyzandeR    schedule 03.05.2017
comment
Спасибо. Как я указал в своем OP, образцов может быть больше 2. Как я могу обобщить ваш код для размещения любого количества образцов. - person neversaint; 03.05.2017
comment
Добро пожаловать. Это уже обобщено. Вот почему я использовал lapply. Вместо lapply(1:2, function(i)... у вас будет lapply(1:as_many_samples_as_you_may_have, function(i)... - person LyzandeR; 03.05.2017

Вот не очень изящный метод:

int <- lapply(1:2, function(x) do.call(data.frame, 
              c(list(CoolFactorScore=my_lol[[1]][[x]]), 
                my_lol[[2]][[x]], 
                list(Sample=my_lol[[3]][[x]])))) 
do.call(rbind, int)

      CoolFactorScore       crt         sr  Sample
B         0.164477631 0.1331186 0.40707688 Sample1
Mac       0.198253819 0.1331186 0.40707688 Sample1
NK        0.396414447 0.1331186 0.40707688 Sample1
Neu       0.133118604 0.1331186 0.40707688 Sample1
Stro      0.107735498 0.1331186 0.40707688 Sample1
B1        0.186215537 0.1840853 0.08291817 Sample2
Mac1      0.184085292 0.1840853 0.08291817 Sample2
NK1       0.375349920 0.1840853 0.08291817 Sample2
Neu1      0.247664923 0.1840853 0.08291817 Sample2
Stro1     0.006684328 0.1840853 0.08291817 Sample2
person Adam Quek    schedule 03.05.2017

Вот решение без цикла с использованием функций пакета data.table.

library(data.table)

шаг 1: разверните список

unlist(my_lol) -> tmp1

Шаг 2: транспонируйте и преобразуйте его в data.table
Таким образом вы получите самую широкую таблицу, которую можно составить из исходных данных. По запросу он должен быть преобразован (в дальнейших шагах) в длинную таблицу.

as.data.table(t(tmp1)) -> tmp2

Шаг 3: «sample_names1» и «sample_names2» необходимо вручную преобразовать в «Sample».
Если вы хотите обобщить несколько значений sample_names, вам следует изменить этот шаг в соответствии с синтаксисом возможных значений. (Эта версия работает для такого синтаксиса значений sample_names, как: 'Sample1', ' Sample2 ',' Sample3 'и т. Д.)

names(tmp2) <- gsub('sample_names\\d+', 'Sample', names(tmp2))

шаг 4: создание имен полей меры на основе имен полей таблицы tmp2

measure <- unique(names(tmp2))

шаг 5: создание более длинной таблицы (tmp3) из широкой таблицы (tmp2)

tmp3 <- melt(tmp2, 
             measure.vars = patterns(measure), 
             value.name = measure)

шаг 6: переименование столбцов согласно запросу

names(tmp3) <- gsub('coolfactor_score.', '', names(tmp3))
names(tmp3) <- gsub('sr_crt.', '', names(tmp3))
setnames(tmp3, 'crt', 'CRT')
setnames(tmp3, 'sr', 'SR')

шаг 7: создание еще более длинной таблицы (mylist) из tmp3

mylist <- melt(tmp3,
               id.vars = c('Sample',
                           'CRT',
                           'SR'),
               measure.vars = c('B', 
                                'Mac',  
                                'NK',   
                                'Neu',
                                'Stro'),
               value.name = 'CoolFactorScore',
               variable.name = 'CellType')

шаг 8: изменение порядка столбцов в соответствии с запросом

setcolorder(mylist, c('CellType', 'Sample', 'CoolFactorScore', 'SR', 'CRT'))

шаг 9: переупорядочивание строк в соответствии с запросом

mylist <- mylist[order(Sample, CellType)]
person sanyi    schedule 04.05.2017