library(knitr)
# print everything as paged ----
knit_print.data.frame <- function (x, options, ...) {
  rmarkdown::paged_table(x, options) |>
    rmarkdown:::print.paged_df()
}
registerS3method("knit_print", "data.frame", knit_print.data.frame)Table printing demo
This code is meant to replicate (and extend) the df_print option in rmarkdown. The code for kable or paged tables is relatively simple, and I have created a more complex function that prints short tables with kableExtra::kable() and longer tables with DT::datatable(). You have to source in the file with the knit_print.data.frame() function for each page in a website or each chapter in a book.
Code
These functions should override knitr::knit_print() for data frames, but wasn’t working at all until I learned in the knit_print vignette that you have to use registerS3method().
df_print: paged
data.frame(x = rnorm(5), y = LETTERS[1:5])df_print: kable
library(knitr)
# print everything as kable ----
knit_print.data.frame <- function (x, options, ...) {
  knitr::kable(x) |> knitr::knit_print(options, ...)
}
registerS3method("knit_print", "data.frame", knit_print.data.frame)data.frame(x = rnorm(5), y = LETTERS[1:5])| x | y | 
|---|---|
| -0.9906570 | A | 
| 0.2181923 | B | 
| 1.0508325 | C | 
| -1.3864300 | D | 
| -0.6493202 | E | 
df_print: custom
Prints tables with 10 or fewer rows using kableExtra::kable() and longer tables with DT::datatable() (unless overridden by options). Includes chunk options for:
- digits (defaults to getOption("digits"))
- rownames (defaults to FALSE)
- pageLength (defaults to 10)
- escape (defaults to TRUE)
- table.cap
library(knitr)
# useful function for options
`%||%` <- function(l, r) {
  if (is.null(l)) r else l
}
# super-customised table printing ----
knit_print.data.frame <- function (x, options, ...) {
  # get options
  digits <- options$digits %||% getOption("digits")
  rownames <- options$rownames %||% FALSE
  pageLength <- options$pageLength %||% 10 
  escape <- options$escape %||% TRUE
  caption <- options$table.cap 
  
  # use DT for longer tables in html
  if (nrow(x) > pageLength & knitr::is_html_output()) {
    numeric_cols <- sapply(x, is.numeric) |> which() |> names()
    dt <- DT::datatable(x, 
                        rownames = rownames,
                        caption = caption,
                        escape = escape,
                        width = "100%",
                        height = "auto",
                        options = list(pageLength = pageLength),
                        selection = "none")
    if (length(numeric_cols) > 0) {
      dt <- DT::formatRound(dt, 
                            columns = numeric_cols,
                            digits = digits)
    }
    knitr::knit_print(dt, options)
  } else {
    # use kableExtra::kable for PDFs or shorter tables
    k <- kableExtra::kable(x, 
                      digits = digits, 
                      row.names = rownames, 
                      caption = caption,
                      escape = escape) |>
      kableExtra::kable_styling(
        full_width = options$full_width,
        bootstrap_options = c("striped", "hover")
      )
    
    if (knitr::is_html_output()) {
        k <- c("<div class=\"kable-table\">", k, "</div>") |>
          paste(collapse = "\n")
    }
    
    knitr::asis_output(k)
  }
}
registerS3method("knit_print", "data.frame", knit_print.data.frame)Test custom df_print
Make data.frame and tbl_df object with 5 and 26 rows.
df5 <- data.frame(x = rnorm(5), y = LETTERS[1:5])
df26 <- data.frame(x = rnorm(26), y = LETTERS)
tbl5 <- tibble::tibble(x = rnorm(5), y = LETTERS[1:5])
tbl26 <- tibble::tibble(x = rnorm(26), y = LETTERS)Should be displayed with kableExtra::kable().
df5| x | y | 
|---|---|
| -0.6516320 | A | 
| 0.5748103 | B | 
| -0.2814253 | C | 
| 0.4269321 | D | 
| -0.8323578 | E | 
Should be displayed with DT::datatable().
df26Should be displayed with kableExtra::kable()
tbl5| x | y | 
|---|---|
| -0.9567718 | A | 
| 0.1482874 | B | 
| -0.3381620 | C | 
| -0.1308482 | D | 
| -0.8651306 | E | 
Should be displayed with DT::datatable()
tbl26Option Tests
Testing options in the r chunk header.
Set the number of digits to display in numeric columns. Defaults to getOption("digits").
# digits = 3
tbl5| x | y | 
|---|---|
| -0.957 | A | 
| 0.148 | B | 
| -0.338 | C | 
| -0.131 | D | 
| -0.865 | E | 
# digits = 4
tbl26rownames are FALSE by default
# rownames = TRUE
tbl5| x | y | |
|---|---|---|
| 1 | -0.9567718 | A | 
| 2 | 0.1482874 | B | 
| 3 | -0.3381620 | C | 
| 4 | -0.1308482 | D | 
| 5 | -0.8651306 | E | 
# rownames = TRUE
tbl26Table captions.
tbl5| x | y | 
|---|---|
| -0.9567718 | A | 
| 0.1482874 | B | 
| -0.3381620 | C | 
| -0.1308482 | D | 
| -0.8651306 | E | 
tbl26Set the page length for DT, if the table is <= to that, will display as kable.
# pageLength = 3, so should be a DT
tbl5# pageLength = 30, so should be a kable
tbl26| x | y | 
|---|---|
| -0.4356147 | A | 
| -1.3184376 | B | 
| -0.9926614 | C | 
| -0.3951119 | D | 
| 0.3668848 | E | 
| 2.0449062 | F | 
| 1.4734182 | G | 
| 1.9424873 | H | 
| 1.3329930 | I | 
| 0.3562878 | J | 
| 1.1314351 | K | 
| 1.4886727 | L | 
| 1.0288225 | M | 
| -0.2596033 | N | 
| -1.2021970 | O | 
| -1.5940632 | P | 
| 1.9479486 | Q | 
| -0.2073134 | R | 
| -0.2618764 | S | 
| -0.5530543 | T | 
| -0.2590854 | U | 
| 0.6115439 | V | 
| 1.1033557 | W | 
| -0.2893176 | X | 
| -2.2715219 | Y | 
| 0.4267168 | Z | 
escape is TRUE by default. Set to FALSE to use html or latex in tables.
# escape = FALSE
tibble::tibble(styles = c("<i>italics</i>", "<b>bold</b>"))| styles | 
|---|
| italics | 
| bold | 
# escape = FALSE
tibble::tibble(styles = rep(c("<i>italics</i>", "<b>bold</b>"), 10))For kable only, defaults to TRUE for html and FALSE for pdf.
# full_width = TRUE
tbl5| x | y | 
|---|---|
| -0.9567718 | A | 
| 0.1482874 | B | 
| -0.3381620 | C | 
| -0.1308482 | D | 
| -0.8651306 | E | 
# full_width = FALSE
tbl5| x | y | 
|---|---|
| -0.9567718 | A | 
| 0.1482874 | B | 
| -0.3381620 | C | 
| -0.1308482 | D | 
| -0.8651306 | E |