MYaseen208
MYaseen208

Reputation: 23898

knitr printing list of data.frames with each table on new page

I want to print list of data.frames with each table on new page. The for-loop works fine but requires long code. Tried with map function but could not get the required output. Not able to use \newpage command with map function. It also gives some extra output like [[1]] NULL [[2]] NULL. Any hint, please.

mt1 <-
  matrix(
    data = runif(n = 200, min = 101, max = 999)
  , nrow = 20
  , ncol = 10
  , byrow = TRUE
  , dimnames = list(LETTERS[1:20], paste0("V", 1:10))
  )

df1 <- data.frame(Name = row.names(mt1), mt1) 

dfs <- 
  unname(
    split.default(
    df1[, -1], as.integer(gl(ncol(df1)-1,  5, ncol(df1) - 1))
    )
    )


library(kableExtra)
library(tidyverse)


for(i in 1:length(dfs)){
  print(
    kable(
      cbind(df1[1], dfs[i])
      , format = 'latex'
      , row.names = FALSE
    ) %>% 
      row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")
    )
  if(i < length(dfs)) {
  cat("\n\n\\newpage\n")
    }
  }

map(
  dfs
  , function(x) 
    print(
      kable(
       cbind(df1[1], x)
      , format = 'latex'
      , row.names = FALSE
    ) %>% 
    row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")
    #cat("\n\n\\newpage\n")
    )
  #if(i < length(x))
    #cat("\n\n\\newpage\n")
  )

Upvotes: 0

Views: 493

Answers (1)

Waldi
Waldi

Reputation: 41220

You can use purrr::imap to get the index in the .y variable:

``` r
library(kableExtra)
library(tidyverse)
library(purrr)

mt1 <-
  matrix(
    data = runif(n = 200, min = 101, max = 999)
    ,
    nrow = 20
    ,
    ncol = 10
    ,
    byrow = TRUE
    ,
    dimnames = list(LETTERS[1:20], paste0("V", 1:10))
  )

df1 <- data.frame(Name = row.names(mt1), mt1)

dfs <-
  unname(split.default(df1[,-1], as.integer(gl(
    ncol(df1) - 1,  5, ncol(df1) - 1
  ))))

f <- function() {
  for (i in 1:length(dfs)) {
    print(
      kable(
        cbind(df1[1], dfs[i])
        ,
        format = 'latex'
        ,
        row.names = FALSE
      ) %>%
        row_spec(
          row = c(0),
          bold = TRUE,
          italic = TRUE,
          align = "l"
        )
    )
    if (i < length(dfs)) {
      cat("\n\n\\newpage\n")
    }
  }
}

f_map <- function() {
  invisible(dfs %>% purrr::imap(~ {
    print(
      kable(cbind(df1[1], .x)
            , format = 'latex'
            , row.names = FALSE) %>%
        row_spec(
          row = c(0),
          bold = TRUE,
          italic = TRUE,
          align = "l"
        )
      #cat("\n\n\\newpage\n")
    )
    if (.y < length(dfs))
      cat("\n\n\\newpage\n")
  }))
}

identical(capture.output(f()), capture.output(f_map()))
#> [1] TRUE

microbenchmark::microbenchmark( f = {res <- capture.output(f())}, f_map = {res <- capture.output(f_map())})
#> Unit: milliseconds
#>   expr      min       lq     mean   median       uq      max neval cld
#>      f 7.908510 8.431997 9.662659 9.012099 10.10318 15.42358   100   a
#>  f_map 7.983586 8.462561 9.797256 9.150356 10.71692 16.20676   100   a
```

<sup>Created on 2020-07-23 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)</sup>

As stated by @CL, this is not faster nor shorter than a simple loop.

Upvotes: 3

Related Questions