Search code examples
rtidyverseknitrpurrrkableextra

R printing each `data.frame` of a list into separate Tables with caption as `data.frame` name


Want to print each data.frame of a list into separate Tables with caption as data.frame name. My attempted code is given below. It produces Tables but with wrong captions.

library(tidyverse)
library(kableExtra)
#> 
#> Attaching package: 'kableExtra'
#> The following object is masked from 'package:dplyr':
#> 
#>     group_rows

df1 <- data.frame(X = 1:3)
df2 <- data.frame(Y = 5:6)

ls1 <-
  list(df1, df2) %>% 
  set_names(c("df1", "df2"))

ls1
#> $df1
#>   X
#> 1 1
#> 2 2
#> 3 3
#> 
#> $df2
#>   Y
#> 1 5
#> 2 6

str(ls1)
#> List of 2
#>  $ df1:'data.frame': 3 obs. of  1 variable:
#>   ..$ X: int [1:3] 1 2 3
#>  $ df2:'data.frame': 2 obs. of  1 variable:
#>   ..$ Y: int [1:2] 5 6
names(ls1)
#> [1] "df1" "df2"

imap(
    .x = ls1
  , .f = ~ {
    kbl(
       x       = .x
     , format  = "markdown"
     , caption = names(.x)
    )
  }
)
#> $df1
#> 
#> 
#> Table: X
#> 
#> |  X|
#> |--:|
#> |  1|
#> |  2|
#> |  3|
#> 
#> $df2
#> 
#> 
#> Table: Y
#> 
#> |  Y|
#> |--:|
#> |  5|
#> |  6|

Solution

  • It should be .y. If it is a named list/vector, the names are by default in .y and the values are in .x which is similar to passing two arguments in map2. If there are no names, then the .y will return the sequence index of the list

    purrr::imap(
      .x = ls1
      , .f = ~ {
        kbl(
          x       = .x
          , format  = "markdown"
          , caption =.y
        )
      }
    )  
    

    -output

    $df1
    
    
    Table: df1
    
    |  X|
    |--:|
    |  1|
    |  2|
    |  3|
    
    $df2
    
    
    Table: df2
    
    |  Y|
    |--:|
    |  5|
    |  6|