Search code examples
rtidyversetidyrnested-lists

How would you create a recursively nested tibble in R


I trying to create what I'm calling a recursively nested tibble, a tibble with x rows that is nested such that each x row nests the following n rows of y. Here is an example of what I'm trying to achieve.

Given the tibble df:

df <- tibble(x = 5:1, y = 5:1)

I'm trying to produce a nested tibble that looks like this: (where data is the nested column)

enter image description here

The one approach I came up with was to use uncount to replicate the original tibble and then add an id column that represents each version of the tibble. Next, I grouped on the id column and then nested the tibble. From here create an index column for each group and filter out what I don't want. This may get me there, but its there must be a more elegant way to achieve this. I'd appreciate any thoughts or insights anyone has.

df <- tibble(x = 5:1, y = 5:1)
z <- uncount(df, 5, .id = "id")
z <- z %>% 
  arrange(id) %>% 
  select(id, x, y) %>% 
  group_by(id) %>% 
  mutate(n = row_number()-1)

Solution

  • Using purrr::map (or lapply) and tidyr::unnest you could do:

    library(dplyr, warn = FALSE)
    library(purrr)
    library(tidyr)
    
    df <- tibble(x = 5:1, y = 5:1)
    
    n <- 3
    
    df |>
      mutate(
        data = map(y, \(x) {
          y <- rev(seq_len(x - 1))
          tibble(y = y[seq_len(min(length(y), n))])
        }),
        .keep = "unused"
      ) |>
      unnest(data, keep_empty = TRUE)
    #> # A tibble: 10 × 2
    #>        x     y
    #>    <int> <int>
    #>  1     5     4
    #>  2     5     3
    #>  3     5     2
    #>  4     4     3
    #>  5     4     2
    #>  6     4     1
    #>  7     3     2
    #>  8     3     1
    #>  9     2     1
    #> 10     1    NA