Home > Back-end >  Dplyr recursively grow a dataframe
Dplyr recursively grow a dataframe

Time:11-05

I have the following values

values <- seq(1,3)

I would like to have the resulting dataframe

# A tibble: 6 x 2
  facet values
  <dbl>  <dbl>
1     1      1
2     2      1
3     2      2
4     3      1
5     3      2
6     3      3

The facet is a column which is stating the iteration of the recursive append.

My current solution is

facet1 <- values %>% head(1) %>% tibble(facet = 1, values = .)
facet2 <- values %>% head(2) %>% tibble(facet = 2, values = .)
facet3 <- values %>% head(3) %>% tibble(facet = 3, values = .)
bind_rows(facet1, facet2, facet3)

A more general solution needed [Edit]

The current solutions will not work for my use-case because they are exploiting the fact that in my previous example sequences of the facets equal the values.

Here is a more general reproducible example where the values are much different from the facets.

set.seed(42)
values <-  rnorm(3,0,.2)
df_recursive <- tribble(~facet, ~values,
        1, 0.27,
        2, 0.27,
        2, -0.11,
        3, 0.27,
        3, -0.11,
        3, 0.07)
# A tibble: 6 x 2
  facet values
  <dbl>  <dbl>
1     1   0.27
2     2   0.27
3     2  -0.11
4     3   0.27
5     3  -0.11
6     3   0.07

CodePudding user response:

Here is an option:

library(tidyverse)

values <- seq(1,3)

map_dfr(values, ~tibble(facet = .x, values = 1:.x))
#> # A tibble: 6 x 2
#>   facet values
#>   <int>  <int>
#> 1     1      1
#> 2     2      1
#> 3     2      2
#> 4     3      1
#> 5     3      2
#> 6     3      3

EDIT: These approaches can all be adapted to your use case. For example:

set.seed(42)
values <-  rnorm(3,0,.2)

map_dfr(1:length(values), ~tibble(facet = .x, values = values[1:.x]))
#> # A tibble: 6 x 2
#>   facet  values
#>   <int>   <dbl>
#> 1     1  0.274 
#> 2     2  0.274 
#> 3     2 -0.113 
#> 4     3  0.274 
#> 5     3 -0.113 
#> 6     3  0.0726

CodePudding user response:

One possible solution:

library(dplyr)

tibble(facet=1:3) %>%
  group_by(facet) %>%
  summarise(values = seq_len(facet)) %>% 
  ungroup()

# A tibble: 6 x 2
  facet values
  <int>  <int>
1     1      1
2     2      1
3     2      2
4     3      1
5     3      2
6     3      3

library(data.table)

data.table(facet=1:3)[, .(values = seq_len(facet)), by=facet]

   facet values
   <int>  <int>
1:     1      1
2:     2      1
3:     2      2
4:     3      1
5:     3      2
6:     3      3

CodePudding user response:

A base R solution, toying around with rep and sequence:

v <- seq(1, 3)
data.frame(facet = rep(v, v), values = sequence(v))

  facet values
1     1      1
2     2      1
3     2      2
4     3      1
5     3      2
6     3      3

This can be adapted to any vector:

set.seed(42)
values <-  rnorm(3, 0, .2)
v <- seq_along(values)
data.frame(facet = rep(v, v), values = values[sequence(v)])

  facet      values
1     1  0.27419169
2     2  0.27419169
3     2 -0.11293963
4     3  0.27419169
5     3 -0.11293963
6     3  0.07262568

And a base R version of AndS.'s solution:

do.call(rbind.data.frame, lapply(v, \(x) data.frame(facet = x, values = seq(x))))
  • Related