2016-12-06 3 views
4

У меня есть data.table следующим образом,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)) 

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

+1

Вы должны прочитать '? Split.data.table' также проверить примеры там. Метод 'split' data.table может создавать вложенные списки. Обязательно обновляйтесь, поскольку 'split.data.table' был введен в v1.9.8. Все в порядке, чтобы ответить на вопрос о себе. – jangorecki

+2

@jangorecki Пожалуйста, напишите ответ. Мне любопытно, как это сделать, и не мог понять, только дойти до «split (my_tab, by = c (« континент »,« страна »), keep.by = FALSE, flatten = FALSE)' где 'my_tab' - это таблица, модифицированная так, чтобы иметь столбцы столбцов вместо коэффициентов (поскольку последний выдает ошибку, по-видимому, связанную с ограничениями столбцов' догрупп'). – Frank

+0

@Frank благодарит за информацию, заглянет в нее – jangorecki

ответ

1

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

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

Вы можете использовать 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 
+1

Есть ли способ элегантно избегать двойного вложения '$ mdl [[1]]'? – Frank

+0

@Frank. Казалось, что это невозможно избежать, поскольку столбец mdl сам по себе является объектами. Если столбец является простым вектором, его можно свести к '$ mdl'. – Psidom