Преобразовать список списков в один кадр данных с первым столбцом, заполненным первым значением (для каждого списка) в R - PullRequest
1 голос
/ 17 апреля 2020

У меня есть список списков, например:

x <-list()
x[[1]] <- c('97', '342', '333')
x[[2]] <- c('97','555','556','742','888')
x[[3]] <- c ('100', '442', '443', '444', '445','446')

Первое число в каждом списке (97, 97, 100) относится к узлу в дереве, а следующие числа относятся к связанным признакам с этим узлом.

Моя цель - создать фрейм данных, который выглядит следующим образом:

df= data.frame(node = c('97','97','97','97','97','97','100','100','100','100','100'),
               trait = c('342','333','555','556','742','888','442','443','444','445','446'))

, где каждая черта имеет свой соответствующий узел.

Я думаю, что первое, что мне нужно сделать, - это преобразовать список списков в один фрейм данных. Я пытался сделать это, используя:

do.call(rbind,x)

, но это повторяет значения в x [[1]] и x [[2]], чтобы соответствовать длине x [[3]]. Я также попытался использовать:

dt_list <- map(x, as.data.table)
dt <- rbindlist(dt_list, fill = TRUE, idcol = T)

Что, я думаю, приближает меня, но я все еще не уверен, как присвоить значение первого узла соответствующим значениям признаков. Я знаю, что это, вероятно, простая задача, но это ставит меня в тупик сегодня!

Ответы [ 4 ]

2 голосов
/ 17 апреля 2020

Может быть, вы можете попробовать код ниже

h <- sapply(x, `[`,1)
d <- lapply(x, `[`,-1)
df <- data.frame(node = rep(h,lengths(d)), trait = unlist(d))

такой, что

> df
   node trait
1    97   342
2    97   333
3    97   555
4    97   556
5    97   742
6    97   888
7   100   442
8   100   443
9   100   444
10  100   445
11  100   446
1 голос
/ 17 апреля 2020

Опция с base R равна

stack(setNames(lapply(x, `[`, -1), sapply(x, `[`, 1)))[2:1]
#   ind values
#1   97    342
#2   97    333
#3   97    555
#4   97    556
#5   97    742
#6   97    888
#7  100    442
#8  100    443
#9  100    444
#10 100    445
#11 100    446
1 голос
/ 17 апреля 2020

Вы можете создать фрейм данных с первым значением из вектора в столбце «узел» и остальными значениями в столбце «черта». Эта стратегия может быть применена ко всем записям в списке, используя функцию map_df() из пакета purrr, предоставляя вывод, который вы описываете.

library(purrr)
library(dplyr)

x %>%
  map_df(., function(vec) data.frame(node = vec[1],
                                     trait = vec[-1], 
                                     stringsAsFactors = F))
0 голосов
/ 17 апреля 2020

Другое решение

library(tidyverse)
library(purrr)
node <- map(x, ~rep(.x[1], length(.x)-1)) %>% flatten_chr()
trait <- map(x, ~.x[2:length(.x)]) %>% flatten_chr()

out <- tibble(node, trait)
  node  trait
  <chr> <chr>
 1 97    342  
 2 97    333  
 3 97    555  
 4 97    556  
 5 97    742  
 6 97    888  
 7 100   442  
 8 100   443  
 9 100   444  
10 100   445  
11 100   446
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...