data.table во вложенный список

У меня есть таблица данных следующим образом:

## install.packages(c("gapminder", "data.table"))
library(gapminder)
library(data.table)
gapminder <- data.table(gapminder)
my_table <- gapminder[, .(mdl = .(lm(lifeExp ~ pop + gdpPercap, 
                                  data = gapminder))), 
                          by = .(country, continent)]

Результирующая таблица будет,

                country continent  mdl
  1:        Afghanistan      Asia <lm>
  2:            Albania    Europe <lm>
  3:            Algeria    Africa <lm>
  4:             Angola    Africa <lm>
  5:          Argentina  Americas <lm>
 ---                                  
138:            Vietnam      Asia <lm>
139: West Bank and Gaza      Asia <lm>
140:        Yemen, Rep.      Asia <lm>
141:             Zambia    Africa <lm>
142:           Zimbabwe    Africa <lm>

Теперь я хочу получить список из этой таблицы данных, так что mdl должен лежать в каждом country, который сам вложен в continent.

Я попытался получить результат как,

first_list <- split(my_table, my_table$continent)
second_list <- lapply(first_list, function(x){ 
                   split(x[, country := as.character(country)], x$country)
               })
final_list <- sapply(second_list, function(x) sapply(x, function(y) y$mdl))

Есть ли какой-нибудь элегантный способ сделать это?


person TheRimalaya    schedule 06.12.2016    source источник
comment
Вы должны прочитать ?split.data.table также посмотреть примеры там. Метод split data.table может создавать вложенные списки. Обязательно обновите, так как split.data.table было введено в версии 1.9.8. Это нормально, чтобы самостоятельно ответить на вопрос SO.   -  person jangorecki    schedule 06.12.2016
comment
@jangorecki Пожалуйста, напишите ответ. Мне любопытно, как это сделать, и я не мог понять это, только дойдя до split(my_tab, by=c("continent", "country"), keep.by = FALSE, flatten = FALSE), где my_tab - это таблица, измененная так, чтобы иметь столбцы char вместо факторов (поскольку последний выдает ошибку, по-видимому, связанную с ограничениями столбцов dogroups) .   -  person Frank    schedule 06.12.2016
comment
@Frank, спасибо за информацию, посмотрю   -  person jangorecki    schedule 06.12.2016
comment
Связано: stackoverflow.com/q/37335072   -  person Frank    schedule 06.12.2016
comment
@Frank Я заполнил #1954 после преобразования в символьный процесс.   -  person jangorecki    schedule 06.12.2016


Ответы (2)


Вы можете получить вложенный список, который вы ищете, с помощью такого кода:

    res<-lapply(unique(my_table$continent),
function(x){lapply(unique(my_table[continent==x]$country),
function(z){my_table[continent==x&country==z]})})
person Bambs    schedule 06.12.2016

Вы можете использовать пакет data.tree :

library(data.tree)
# create a path string
my_table$pathString <- paste("world", my_table$continent, my_table$country, sep = "/")

# convert the data.table to nodes and nested lists
nested_list <- as.list(as.Node(my_table[, .(pathString, mdl)]))

# query the result
nested_list[["Asia"]][["Vietnam"]]

#$mdl
#$mdl[[1]]

#Call:
#lm(formula = lifeExp ~ pop + gdpPercap, data = gapminder)

#Coefficients:
#(Intercept)          pop    gdpPercap  
#  5.365e+01    9.728e-09    7.676e-04  

Или другой вариант:

nested_list <- lapply(split(my_table, by = "continent"), 
                      function(dt) setNames(dt$mdl, dt$country))

nested_list[["Asia"]][["Vietnam"]]

#Call:
#lm(formula = lifeExp ~ pop + gdpPercap, data = gapminder)

#Coefficients:
#(Intercept)          pop    gdpPercap  
#  5.365e+01    9.728e-09    7.676e-04  
person Psidom    schedule 06.12.2016
comment
Есть ли способ элегантно избежать двойной вложенности $mdl[[1]] ? - person Frank; 06.12.2016
comment
@Откровенный. Казалось, этого нельзя избежать, поскольку столбец mdl сам по себе является объектом. Если столбец представляет собой простой вектор, его можно уменьшить до $mdl. - person Psidom; 06.12.2016