Search code examples
rknitrkablekableextra

Efficient way to print large data.frame with kable


I want to print a large data.frame with kable. I divided the data.frame into parts. Is there a more efficient method with less code?

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

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

library(kableExtra)

kable(df1[,c(1, 2:6)], format = "rst", row.names = FALSE)
kable(df1[,c(1, 7:11)], format = "rst", row.names = FALSE)
kable(df1[,c(1, 12:16)], format = "rst", row.names = FALSE)
kable(df1[,c(1, 17:21)], format = "rst", row.names = FALSE)

Edited

library(tidyverse)
kable(df1[,c(1, 2:6)], format = "latex", row.names = FALSE) %>% 
  row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")

kable(df1[,c(1, 7:11)], format = "latex", row.names = FALSE) %>% 
  row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")

kable(df1[,c(1, 12:16)], format = "latex", row.names = FALSE) %>% 
  row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")

kable(df1[,c(1, 17:21)], format = "latex", row.names = FALSE) %>% 
  row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")

Solution

  • We can create the index and pass it to Map

    Map(function(i, j) kable(df1[c(1, i:j)], format = 'rst', 
            row.names = FALSE), seq(2, 17, by = 5), seq(6, 21, by = 5))
    

    Or use split with a grouping index created with gl

    lapply(split.default(df1[, -1], as.integer(gl(ncol(df1)-1,  5,
      ncol(df1) - 1))), function(x) 
             kable(cbind(df1[1], x), format = 'rst', row.names = FALSE))
    #$`1`
    
    
    #====  ========  ========  ========  ========  ========
    #Name        V1        V2        V3        V4        V5
    #====  ========  ========  ========  ========  ========
    #A     359.0833  809.0627  150.5985  651.3763  200.7702
    #B     338.8996  388.5825  612.0037  695.4628  709.0798
    #C     760.0153  423.7709  956.7838  799.0494  663.9588
    #D     319.5298  683.4278  144.7564  757.8725  694.7529
    #E     294.5364  954.1390  223.0555  227.9699  347.4535
    #F     117.1561  281.8261  205.4815  265.4050  227.5070
    #G     944.5761  312.9263  741.1121  533.0935  833.5107
    #H     145.8520  223.1062  802.7357  570.6363  871.7380
    #I     591.0673  490.9409  722.8031  307.7193  226.9439
    #J     152.7567  756.3408  970.0148  941.1165  125.0778
    #====  ========  ========  ========  ========  ========
    
    #$`2`
    #...
    

    With the edits, it would be

    lapply(split.default(df1[, -1], as.integer(gl(ncol(df1)-1,  5,
      ncol(df1) - 1))), function(x) 
             kable(cbind(df1[1], x), format = 'latex', row.names = FALSE) %>% 
                 row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l"))
    

    If we want to add a pagebreak

    f1 <- function(dat, i1, i2) {
         kable(dat[, c(1, i1:i2)], format = "latex", row.names = FALSE) %>% 
             row_spec(row = c(0), bold = TRUE, italic = TRUE, align = "l")}
    
    v1 <- seq(2, 17, by = 5)
    v2 <- seq(6, 21, by = 5)
    for(i in seq_along(v1) {
        print(f1(df1, v1[i], v2[i]))
        if(i < length(v1)) {
         cat("\n\n\\pagebreak\n")
          }
        }