Search code examples
rlistdataframepurrrtibble

Add a row to each dataframe in a list with the column median using map_dfr


I have this example list that contains 3 dataframes:

library(tidyverse)
list_df <- iris %>% 
    group_by(Species) %>% 
    slice(1:3) %>% 
    ungroup() %>% 
    group_split(Species)

I want to add a new row at the end of each dataframe that shows the column median

My try so far (and earlier this day I am sure it worked) is not working:

list_df %>%
    map_dfr([,1:4], ~ .x %>%
                add_row(!!!map(., median)))

I want to learn why my code is not working and what exactly !!! is for ins this situation.


Solution

  • The [, 1:4] doesn't include the data i.e. it only shows the index and thus it fails

    list_df %>% 
            map_dfr(~ .x %>% 
                 add_row(!!! map(.[1:4], median)))
    

    -output

    # A tibble: 12 x 5
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species   
              <dbl>       <dbl>        <dbl>       <dbl> <fct>     
     1          5.1         3.5          1.4         0.2 setosa    
     2          4.9         3            1.4         0.2 setosa    
     3          4.7         3.2          1.3         0.2 setosa    
     4          4.9         3.2          1.4         0.2 <NA>      
     5          7           3.2          4.7         1.4 versicolor
     6          6.4         3.2          4.5         1.5 versicolor
     7          6.9         3.1          4.9         1.5 versicolor
     8          6.9         3.2          4.7         1.5 <NA>      
     9          6.3         3.3          6           2.5 virginica 
    10          5.8         2.7          5.1         1.9 virginica 
    11          7.1         3            5.9         2.1 virginica 
    12          6.3         3            5.9         2.1 <NA>      
    

    If we want to add a row with the group information, another option is group_modify (without splitting)

    iris %>% 
        group_by(Species) %>% 
        slice(1:3) %>%
        group_modify(~ .x %>% 
                    add_row(!!! map(.x, median))) %>% 
        ungroup
    

    -output

    # A tibble: 12 x 5
       Species    Sepal.Length Sepal.Width Petal.Length Petal.Width
       <fct>             <dbl>       <dbl>        <dbl>       <dbl>
     1 setosa              5.1         3.5          1.4         0.2
     2 setosa              4.9         3            1.4         0.2
     3 setosa              4.7         3.2          1.3         0.2
     4 setosa              4.9         3.2          1.4         0.2
     5 versicolor          7           3.2          4.7         1.4
     6 versicolor          6.4         3.2          4.5         1.5
     7 versicolor          6.9         3.1          4.9         1.5
     8 versicolor          6.9         3.2          4.7         1.5
     9 virginica           6.3         3.3          6           2.5
    10 virginica           5.8         2.7          5.1         1.9
    11 virginica           7.1         3            5.9         2.1
    12 virginica           6.3         3            5.9         2.1
    

    If we want to add the median rows,

    iris %>% 
        group_by(Species) %>% 
        slice(1:3) %>%
        group_modify(~ .x %>% 
                    add_row(!!! map(.x, median))) %>%
        mutate(rn = row_number()) %>%
        ungroup %>% 
        summarise(across(2:5, ~ c(.[rn < max(rn)], 
          sum(.[rn == max(rn)]))), Species = c(Species[rn != max(rn)],
            "Total"))
    

    -output

    # A tibble: 10 x 5
       Sepal.Length Sepal.Width Petal.Length Petal.Width Species
              <dbl>       <dbl>        <dbl>       <dbl> <chr>  
     1          5.1         3.5          1.4         0.2 1      
     2          4.9         3            1.4         0.2 1      
     3          4.7         3.2          1.3         0.2 1      
     4          7           3.2          4.7         1.4 2      
     5          6.4         3.2          4.5         1.5 2      
     6          6.9         3.1          4.9         1.5 2      
     7          6.3         3.3          6           2.5 3      
     8          5.8         2.7          5.1         1.9 3      
     9          7.1         3            5.9         2.1 3      
    10         18.1         9.4         12           3.8 Total