This function iout_nest performs an “inside-out” version of what tidyr::nest does. The data table is a collation of all the nested sub-tables, and the main table is linked parent of those.
My question, is there an existing package or idiom in R that already performs this kind of inside-out nesting?
library(dplyr)
library(tidyr)
#' using the nest() idioms, turn the main and sub-tables inside out into 2 tables
#' keyed by "id"
iout_nest <- function(x, ...) {
nested <- nest(x, ..., .key = "_data_")
out <- list(data = dplyr::bind_rows(nested[["_data_"]], .id = "id"))
nested[["_data_"]] <- NULL
nested[["id"]] <- as.character(seq_len(nrow(nested)))
out[["main"]] <- nested
out
}
The nested iris table.
(d1 <- iris %>% nest(-Species, -Petal.Width))
## # A tibble: 27 × 3
## Petal.Width Species data
## <dbl> <fctr> <list>
## 1 0.2 setosa <tibble [29 × 3]>
## 2 0.4 setosa <tibble [7 × 3]>
## 3 0.3 setosa <tibble [7 × 3]>
## 4 0.1 setosa <tibble [5 × 3]>
## 5 0.5 setosa <tibble [1 × 3]>
## 6 0.6 setosa <tibble [1 × 3]>
## 7 1.4 versicolor <tibble [7 × 3]>
## 8 1.5 versicolor <tibble [10 × 3]>
## 9 1.3 versicolor <tibble [13 × 3]>
## 10 1.6 versicolor <tibble [3 × 3]>
## # ... with 17 more rows
Turn the same nesting inside-out, into two tables.
(d2 <- iris %>% iout_nest(-Species, -Petal.Width))
## $data
## # A tibble: 150 × 4
## id Sepal.Length Sepal.Width Petal.Length
## <chr> <dbl> <dbl> <dbl>
## 1 1 5.1 3.5 1.4
## 2 1 4.9 3.0 1.4
## 3 1 4.7 3.2 1.3
## 4 1 4.6 3.1 1.5
## 5 1 5.0 3.6 1.4
## 6 1 5.0 3.4 1.5
## 7 1 4.4 2.9 1.4
## 8 1 5.4 3.7 1.5
## 9 1 4.8 3.4 1.6
## 10 1 5.8 4.0 1.2
## # ... with 140 more rows
##
## $main
## # A tibble: 27 × 3
## Petal.Width Species id
## <dbl> <fctr> <chr>
## 1 0.2 setosa 1
## 2 0.4 setosa 2
## 3 0.3 setosa 3
## 4 0.1 setosa 4
## 5 0.5 setosa 5
## 6 0.6 setosa 6
## 7 1.4 versicolor 7
## 8 1.5 versicolor 8
## 9 1.3 versicolor 9
## 10 1.6 versicolor 10
## # ... with 17 more rows
## compare with iris after joining back together
all.equal(d2$data %>% inner_join(d2$main) %>% select(-id), iris)
## Joining, by = "id"
## [1] TRUE