yihui / knitr
1
#' Create tables in LaTeX, HTML, Markdown and reStructuredText
2
#'
3
#' A very simple table generator, and it is simple by design. It is not intended
4
#' to replace any other R packages for making tables. The \code{kable()}
5
#' function returns a single table for a single data object, and returns a table
6
#' that contains multiple tables if the input object is a list of data objects.
7
#' The \code{kables()} function is similar to \code{kable(x)} when \code{x} is a
8
#' list of data objects, but \code{kables()} accepts a list of \code{kable()}
9
#' values directly instead of data objects (see examples below).
10
#'
11
#' Missing values (\code{NA}) in the table are displayed as \code{NA} by
12
#' default. If you want to display them with other characters, you can set the
13
#' option \code{knitr.kable.NA}, e.g. \code{options(knitr.kable.NA = '')} to
14
#' hide \code{NA} values.
15
#' @param x For \code{kable()}, \code{x} is an R object, which is typically a
16
#'   matrix or data frame. For \code{kables()}, a list with each element being a
17
#'   returned value from \code{kable()}.
18
#' @param format A character string. Possible values are \code{latex},
19
#'   \code{html}, \code{pipe} (Pandoc's pipe tables), \code{simple} (Pandoc's
20
#'   simple tables), and \code{rst}. The value of this argument will be
21
#'   automatically determined if the function is called within a \pkg{knitr}
22
#'   document. The \code{format} value can also be set in the global option
23
#'   \code{knitr.table.format}. If \code{format} is a function, it must return a
24
#'   character string.
25
#' @param digits Maximum number of digits for numeric columns, passed to
26
#'   \code{round()}. This can also be a vector of length \code{ncol(x)}, to set
27
#'   the number of digits for individual columns.
28
#' @param row.names Logical: whether to include row names. By default, row names
29
#'   are included if \code{rownames(x)} is neither \code{NULL} nor identical to
30
#'   \code{1:nrow(x)}.
31
#' @param col.names A character vector of column names to be used in the table.
32
#' @param align Column alignment: a character vector consisting of \code{'l'}
33
#'   (left), \code{'c'} (center) and/or \code{'r'} (right). By default or if
34
#'   \code{align = NULL}, numeric columns are right-aligned, and other columns
35
#'   are left-aligned. If \code{length(align) == 1L}, the string will be
36
#'   expanded to a vector of individual letters, e.g. \code{'clc'} becomes
37
#'   \code{c('c', 'l', 'c')}, unless the output format is LaTeX.
38
#' @param caption The table caption.
39
#' @param label The table reference label. By default, the label is obtained
40
#'   from \code{knitr::\link{opts_current}$get('label')}.
41
#' @param format.args A list of arguments to be passed to \code{\link{format}()}
42
#'   to format table values, e.g. \code{list(big.mark = ',')}.
43
#' @param escape Boolean; whether to escape special characters when producing
44
#'   HTML or LaTeX tables. When \code{escape = FALSE}, you have to make sure
45
#'   that special characters will not trigger syntax errors in LaTeX or HTML.
46
#' @param ... Other arguments (see Examples and References).
47
#' @return A character vector of the table source code.
48
#' @seealso Other R packages such as \pkg{huxtable}, \pkg{xtable},
49
#'   \pkg{kableExtra}, \pkg{gt} and \pkg{tables} for HTML and LaTeX tables, and
50
#'   \pkg{ascii} and \pkg{pander} for different flavors of markdown output and
51
#'   some advanced features and table styles. For more on other packages for
52
#'   creating tables, see
53
#'   \url{https://bookdown.org/yihui/rmarkdown-cookbook/table-other.html}.
54
#' @note When using \code{kable()} as a \emph{top-level} expression, you do not
55
#'   need to explicitly \code{print()} it due to R's automatic implicit
56
#'   printing. When it is wrapped inside other expressions (such as a
57
#'   \code{\link{for}} loop), you must explicitly \code{print(kable(...))}.
58
#' @references See
59
#'   \url{https://bookdown.org/yihui/rmarkdown-cookbook/kable.html} for some
60
#'   examples about this function, including specific arguments according to the
61
#'   \code{format} selected.
62
#' @export
63
#' @examples d1 = head(iris); d2 = head(mtcars)
64
#' # pipe tables by default
65
#' kable(d1)
66
#' kable(d2[, 1:5])
67
#' # no inner padding
68
#' kable(d2, format = 'pipe', padding = 0)
69
#' # more padding
70
#' kable(d2, format = 'pipe', padding = 2)
71
#' kable(d1, format = 'latex')
72
#' kable(d1, format = 'html')
73
#' kable(d1, format = 'latex', caption = 'Title of the table')
74
#' kable(d1, format = 'html', caption = 'Title of the table')
75
#' # use the booktabs package
76
#' kable(mtcars, format = 'latex', booktabs = TRUE)
77
#' # use the longtable package
78
#' kable(matrix(1000, ncol=5), format = 'latex', digits = 2, longtable = TRUE)
79
#' # change LaTeX default table environment
80
#' kable(d1, format = "latex", caption = "My table", table.envir='table*')
81
#' # add some table attributes
82
#' kable(d1, format = 'html', table.attr = 'id="mytable"')
83
#' # reST output
84
#' kable(d2, format = 'rst')
85
#' # no row names
86
#' kable(d2, format = 'rst', row.names = FALSE)
87
#' # Pandoc simple tables
88
#' kable(d2, format = 'simple', caption = 'Title of the table')
89
#' # format numbers using , as decimal point, and ' as thousands separator
90
#' x = as.data.frame(matrix(rnorm(60, 1e6, 1e4), 10))
91
#' kable(x, format.args = list(decimal.mark = ',', big.mark = "'"))
92
#' # save the value
93
#' x = kable(d2, format = 'html')
94
#' cat(x, sep = '\n')
95
#' # can also set options(knitr.table.format = 'html') so that the output is HTML
96
#'
97
#' # multiple tables via either kable(list(x1, x2)) or kables(list(kable(x1), kable(x2)))
98
#' kable(list(d1, d2), caption = 'A tale of two tables')
99
#' kables(list(kable(d1, align = 'l'), kable(d2)), caption = 'A tale of two tables')
100
kable = function(
101
  x, format, digits = getOption('digits'), row.names = NA, col.names = NA,
102
  align, caption = NULL, label = NULL, format.args = list(), escape = TRUE, ...
103
) {
104

105 1
  format = kable_format(format)
106
  # expand align if applicable
107 1
  if (!missing(align) && length(align) == 1L && !grepl('[^lcr]', align))
108 1
    align = strsplit(align, '')[[1]]
109

110 1
  if (inherits(x, 'list')) {
111 0
    format = kable_format_latex(format)
112 0
    res = lapply(
113 0
      x, kable, format = format, digits = digits, row.names = row.names,
114 0
      col.names = col.names, align = align, caption = NA,
115 0
      format.args = format.args, escape = escape, ...
116
    )
117 0
    return(kables(res, format, caption, label))
118
  }
119

120 1
  caption = kable_caption(label, caption, format)
121

122 1
  if (!is.matrix(x)) x = as.data.frame(x)
123 1
  if (identical(col.names, NA)) col.names = colnames(x)
124 1
  m = ncol(x)
125
  # numeric columns
126 1
  isn = if (is.matrix(x)) rep(is.numeric(x), m) else sapply(x, is.numeric)
127 1
  if (missing(align) || (format == 'latex' && is.null(align)))
128 1
    align = ifelse(isn, 'r', 'l')
129
  # rounding
130 1
  digits = rep(digits, length.out = m)
131 1
  for (j in seq_len(m)) {
132 1
    if (is_numeric(x[, j])) x[, j] = round(x[, j], digits[j])
133
  }
134 1
  if (any(isn)) {
135 1
    if (is.matrix(x)) {
136 0
      if (is.table(x) && length(dim(x)) == 2) class(x) = 'matrix'
137 1
      x = format_matrix(x, format.args)
138 1
    } else x[, isn] = format_args(x[, isn], format.args)
139
  }
140 1
  if (is.na(row.names)) row.names = has_rownames(x)
141 1
  if (!is.null(align)) align = rep(align, length.out = m)
142 1
  if (row.names) {
143 1
    x = cbind(' ' = rownames(x), x)
144 1
    if (!is.null(col.names)) col.names = c(' ', col.names)
145 1
    if (!is.null(align)) align = c('l', align)  # left align row names
146
  }
147 1
  n = nrow(x)
148 1
  x = replace_na(to_character(x), is.na(x))
149 0
  if (!is.matrix(x)) x = matrix(x, nrow = n)
150 1
  x = trimws(x)
151 1
  colnames(x) = col.names
152 1
  if (format != 'latex' && length(align) && !all(align %in% c('l', 'r', 'c')))
153 0
    stop("'align' must be a character vector of possible values 'l', 'r', and 'c'")
154 1
  attr(x, 'align') = align
155 1
  res = do.call(
156 1
    paste('kable', format, sep = '_'),
157 1
    list(x = x, caption = caption, escape = escape, ...)
158
  )
159 1
  structure(res, format = format, class = 'knitr_kable')
160
}
161

162
kable_caption = function(label, caption, format) {
163
  # create a label for bookdown if applicable
164 1
  if (is.null(label)) label = opts_current$get('label')
165 1
  if (!is.null(caption) && !is.na(caption)) caption = paste0(
166 1
    create_label('tab:', label, latex = (format == 'latex')), caption
167
  )
168 1
  caption
169
}
170

171
# determine the table format
172
kable_format = function(format = NULL) {
173 1
  if (missing(format) || is.null(format)) format = getOption('knitr.table.format')
174 1
  if (is.null(format)) format = if (is.null(pandoc_to())) switch(
175 1
    out_format() %n% 'markdown',
176 1
    latex = 'latex', listings = 'latex', sweave = 'latex',
177 1
    html = 'html', markdown = 'pipe', rst = 'rst',
178 1
    stop('table format not implemented yet!')
179 1
  ) else if (isTRUE(opts_knit$get('kable.force.latex')) && is_latex_output()) {
180
    # force LaTeX table because Pandoc's longtable may not work well with floats
181
    # http://tex.stackexchange.com/q/276699/9128
182 0
    'latex'
183 1
  } else 'pipe'
184 0
  if (is.function(format)) format = format()
185
  # backward compatibility with knitr <= v1.28
186 1
  switch(format, pandoc = 'simple', markdown = 'pipe', format)
187
}
188

189
# if the output is for Pandoc and we want multiple tabular in one table, we
190
# should use the latex format instead, because Pandoc does not support Markdown
191
# in LaTeX yet https://github.com/jgm/pandoc/issues/2453
192
kable_format_latex = function(format) {
193 0
  if (format == 'pipe' && is_latex_output()) 'latex' else format
194
}
195

196
#' @rdname kable
197
#' @export
198
kables = function(x, format, caption = NULL, label = NULL) {
199 0
  format = kable_format(format)
200 0
  format = kable_format_latex(format)
201 0
  caption = kable_caption(label, caption, format)
202
  # in case `x` contains kable()s, make sure all kable()s use the same default format
203 0
  opts = options(knitr.table.format = format); on.exit(options(opts), add = TRUE)
204 0
  if (!inherits(x, 'list')) stop("'x' must be a list (of kable() values)")
205 0
  res = unlist(lapply(x, one_string))
206 0
  res = if (format == 'latex') {
207 0
    kable_latex_caption(res, caption)
208 0
  } else if (format == 'html' || (format == 'pipe' && is_html_output())) kable_html(
209 0
    matrix(paste0('\n\n', res, '\n\n'), 1), caption = caption, escape = FALSE,
210 0
    table.attr = 'class="kable_wrapper"'
211
  ) else {
212 0
    res = paste(res, collapse = '\n\n')
213 0
    if (format == 'pipe') kable_pandoc_caption(res, caption) else res
214
  }
215 0
  structure(res, format = format, class = 'knitr_kable')
216
}
217

218
# convert to character while preserving dim/dimnames attributes
219
to_character = function(x) {
220 1
  if (is.character(x)) return(x)
221
  # format columns individually if x is not a matrix
222 1
  if (!is.matrix(x)) {
223 1
    for (j in seq_len(ncol(x))) x[, j] = format_args(x[, j])
224 1
    x = as.matrix(x)
225
  }
226 1
  x2 = as.character(x); dim(x2) = dim(x); dimnames(x2) = dimnames(x)
227 1
  x2
228
}
229

230
# as.data.frame() does not allow duplicate row names (#898)
231
format_matrix = function(x, args) {
232 1
  nms = rownames(x)
233 1
  rownames(x) = NULL
234 1
  x = as.matrix(format_args(as.data.frame(x), args))
235 1
  rownames(x) = nms
236 1
  x
237
}
238

239
format_args = function(x, args = list()) {
240 1
  args$x = x
241 1
  args$trim = TRUE
242 1
  replace_na(do.call(format, args), is.na(x))
243
}
244

245
replace_na = function(x, which = is.na(x), to = getOption('knitr.kable.NA')) {
246 1
  if (is.null(to)) return(x)
247 1
  x[which] = to
248 1
  x
249
}
250

251
has_rownames = function(x) {
252 1
  !is.null(rownames(x)) && !identical(rownames(x), as.character(seq_len(NROW(x))))
253
}
254

255
#' @export
256
print.knitr_kable = function(x, ...) {
257 0
  if (!(attr(x, 'format') %in% c('html', 'latex'))) cat('\n\n')
258 0
  cat(x, sep = '\n')
259
}
260

261
#' @export
262
knit_print.knitr_kable = function(x, ...) {
263 0
  x = one_string(c(
264 0
    if (!(attr(x, 'format') %in% c('html', 'latex'))) c('', ''), x, '\n'
265
  ))
266 0
  asis_output(x)
267
}
268

269
kable_latex = function(
270
  x, booktabs = FALSE, longtable = FALSE, valign = 't', position = '', centering = TRUE,
271
  vline = getOption('knitr.table.vline', if (booktabs) '' else '|'),
272
  toprule = getOption('knitr.table.toprule', if (booktabs) '\\toprule' else '\\hline'),
273
  bottomrule = getOption('knitr.table.bottomrule', if (booktabs) '\\bottomrule' else '\\hline'),
274
  midrule = getOption('knitr.table.midrule', if (booktabs) '\\midrule' else '\\hline'),
275
  linesep = if (booktabs) c('', '', '', '', '\\addlinespace') else '\\hline',
276
  caption = NULL, caption.short = '', table.envir = if (!is.null(caption)) 'table',
277
  escape = TRUE
278
) {
279 1
  if (!is.null(align <- attr(x, 'align'))) {
280 1
    align = paste(align, collapse = vline)
281 1
    align = paste0('{', align, '}')
282
  }
283 1
  centering = if (centering && !is.null(caption)) '\n\\centering'
284
  # vertical align only if 'caption' is not NULL (may be NA) or 'valign' has
285
  # been explicitly specified
286 1
  valign = if ((!is.null(caption) || !missing(valign)) && valign != '') {
287 0
    sprintf('[%s]', valign)
288
  } else ''
289 0
  if (identical(caption, NA)) caption = NULL
290 0
  if (position != '') position = paste0('[', position, ']')
291 1
  env1 = sprintf('\\begin{%s}%s\n', table.envir, position)
292 1
  env2 = sprintf('\n\\end{%s}',   table.envir)
293 0
  if (caption.short != '') caption.short = paste0('[', caption.short, ']')
294 1
  cap = if (is.null(caption)) '' else sprintf('\n\\caption%s{%s}', caption.short, caption)
295

296 1
  if (nrow(x) == 0) midrule = ""
297

298 1
  linesep = if (nrow(x) > 1) {
299 1
    c(rep(linesep, length.out = nrow(x) - 1), '')
300 1
  } else rep('', nrow(x))
301 1
  linesep = ifelse(linesep == "", linesep, paste0('\n', linesep))
302

303 1
  if (escape) x = escape_latex(x)
304 0
  if (!is.character(toprule)) toprule = NULL
305 0
  if (!is.character(bottomrule)) bottomrule = NULL
306 1
  tabular = if (longtable) 'longtable' else 'tabular'
307

308 1
  paste(c(
309 1
    if (!longtable) c(env1, cap, centering),
310 1
    sprintf('\n\\begin{%s}%s', tabular, valign), align,
311 1
    if (longtable && cap != '') c(cap, '\\\\'),
312 1
    sprintf('\n%s', toprule), '\n',
313 1
    if (!is.null(cn <- colnames(x))) {
314 1
      if (escape) cn = escape_latex(cn)
315 1
      paste0(paste(cn, collapse = ' & '), sprintf('\\\\\n%s\n', midrule))
316
    },
317 1
    one_string(apply(x, 1, paste, collapse = ' & '), sprintf('\\\\%s', linesep), sep = ''),
318 1
    sprintf('\n%s', bottomrule),
319 1
    sprintf('\n\\end{%s}', tabular),
320 1
    if (!longtable) env2
321 1
  ), collapse = '')
322
}
323

324
kable_latex_caption = function(x, caption) {
325 0
  paste(c(
326 0
    '\\begin{table}\n', sprintf('\\caption{%s}\n', caption), x, '\n\\end{table}'
327 0
  ), collapse = '')
328
}
329

330
kable_html = function(x, table.attr = '', caption = NULL, escape = TRUE, ...) {
331 1
  table.attr = trimws(table.attr)
332
  # need a space between <table and attributes
333 0
  if (nzchar(table.attr)) table.attr = paste('', table.attr)
334 1
  align = if (is.null(align <- attr(x, 'align'))) '' else {
335 1
    sprintf(' style="text-align:%s;"', c(l = 'left', c = 'center', r = 'right')[align])
336
  }
337 0
  if (identical(caption, NA)) caption = NULL
338 1
  cap = if (length(caption)) sprintf('\n<caption>%s</caption>', caption) else ''
339 1
  if (escape) x = escape_html(x)
340 1
  one_string(c(
341 1
    sprintf('<table%s>%s', table.attr, cap),
342 1
    if (!is.null(cn <- colnames(x))) {
343 1
      if (escape) cn = escape_html(cn)
344 1
      c(' <thead>', '  <tr>', sprintf('   <th%s> %s </th>', align, cn), '  </tr>', ' </thead>')
345
    },
346 1
    '<tbody>',
347 1
    paste(
348 1
      '  <tr>',
349 1
      apply(x, 1, function(z) one_string(sprintf('   <td%s> %s </td>', align, z))),
350 1
      '  </tr>', sep = '\n'
351
    ),
352 1
    '</tbody>',
353 1
    '</table>'
354
  ))
355
}
356

357
#' Generate tables for Markdown and reST
358
#'
359
#' This function provides the basis for Markdown and reST tables.
360
#' @param x The data matrix.
361
#' @param sep.row A length-3 character vector, specifying separators to be printed
362
#'   before the header, after the header, and at the end of the table respectively.
363
#' @param sep.col The column separator.
364
#' @param padding Number of spaces for the table cell padding.
365
#' @param align.fun A function to process the separator under the header
366
#'   according to the alignment.
367
#' @return A character vector of the table content.
368
#' @noRd
369
kable_mark = function(x, sep.row = c('=', '=', '='), sep.col = '  ', padding = 0,
370
                      align.fun = function(s, a) s, rownames.name = '', ...) {
371
  # when the column separator is |, replace existing | with its HTML entity
372 1
  if (sep.col == '|') for (j in seq_len(ncol(x))) {
373 1
    x[, j] = gsub('\\|', '&#124;', x[, j])
374
  }
375 1
  l = if (prod(dim(x)) > 0) apply(x, 2, function(z) max(nchar(z, type = 'width'), na.rm = TRUE))
376 1
  cn = colnames(x)
377 1
  if (length(cn) > 0) {
378 1
    cn[is.na(cn)] = "NA"
379 1
    if (sep.col == '|') cn = gsub('\\|', '&#124;', cn)
380 1
    if (grepl('^\\s*$', cn[1L])) cn[1L] = rownames.name  # no empty cells for reST
381 1
    l = pmax(if (length(l) == 0) 0 else l, nchar(cn, type = 'width'))
382
  }
383 1
  align = attr(x, 'align')
384 1
  padding = padding * if (length(align) == 0) 2 else {
385 1
    ifelse(align == 'c', 2, 1)
386
  }
387 1
  l = pmax(l + padding, 3)  # at least of width 3 for Github Markdown
388 1
  s = unlist(lapply(l, function(i) paste(rep(sep.row[2], i), collapse = '')))
389 1
  res = rbind(if (!is.na(sep.row[1])) s, cn, align.fun(s, align),
390 1
              x, if (!is.na(sep.row[3])) s)
391 1
  apply(mat_pad(res, l, align), 1, paste, collapse = sep.col)
392
}
393

394
kable_rst = function(x, rownames.name = '\\', ...) {
395 1
  kable_mark(x, rownames.name = rownames.name)
396
}
397

398
# Pandoc's pipe table
399
kable_pipe = function(x, caption = NULL, padding = 1, ...) {
400 1
  if (is.null(colnames(x))) {
401 1
    warning('The table should have a header (column names)')
402 1
    colnames(x) = rep('', ncol(x))
403
  }
404 1
  res = kable_mark(x, c(NA, '-', NA), '|', padding, align.fun = function(s, a) {
405 0
    if (is.null(a)) return(s)
406 1
    r = c(l = '^.', c = '^.|.$', r = '.$')
407 1
    for (i in seq_along(s)) {
408 1
      s[i] = gsub(r[a[i]], ':', s[i])
409
    }
410 1
    s
411
  }, ...)
412 1
  res = sprintf('|%s|', res)
413 1
  kable_pandoc_caption(res, caption)
414
}
415

416
# Pandoc's simple table
417
kable_simple = function(x, caption = NULL, padding = 1, ...) {
418
  # simple tables do not support 1-column or 0-row tables
419 1
  tab = if (ncol(x) == 1 || nrow(x) == 0) kable_pipe(
420 1
    x, padding = padding, ...
421 1
  ) else kable_mark(
422 1
    x, c(NA, '-', if (is_blank(colnames(x))) '-' else NA),
423 1
    padding = padding, ...
424
  )
425 1
  kable_pandoc_caption(tab, caption)
426
}
427

428
kable_pandoc_caption = function(x, caption) {
429 0
  if (identical(caption, NA)) caption = NULL
430 1
  if (length(caption)) c(paste('Table:', caption), "", x) else x
431
}
432

433
# pad a matrix
434
mat_pad = function(m, width, align = NULL) {
435 1
  n = nrow(m); p = ncol(m)
436 1
  res = matrix('', nrow = n, ncol = p)
437 1
  if (n * p == 0) return(res)
438 1
  stopifnot(p == length(width))
439 1
  side = rep('both', p)
440 1
  if (!is.null(align)) side = c(l = 'right', c = 'both', r = 'left')[align]
441 1
  apply(m, 2, function(x) max(nchar(x, 'width') - nchar(x, 'chars')))
442 1
  matrix(pad_width(c(m), rep(width, each = n), rep(side, each = n)), ncol = p)
443
}
444

445
# pad a character vector to width (instead of number of chars), considering the
446
# case of width > chars (e.g. CJK chars)
447
pad_width = function(x, width, side) {
448 1
  if (!all(side %in% c('left', 'right', 'both')))
449 0
    stop("'side' must be 'left', 'right', or 'both'")
450 1
  w = width - nchar(x, 'width')
451 1
  w1 = floor(w / 2)  # the left half of spaces when side = 'both'
452 1
  s1 = v_spaces(w * (side == 'left') + w1 * (side == 'both'))
453 1
  s2 = v_spaces(w * (side == 'right') + (w - w1) * (side == 'both'))
454 1
  paste0(s1, x, s2)
455
}
456

457
# vectorized over n to generate sequences of spaces
458
v_spaces = function(n) {
459 1
  unlist(lapply(n, highr:::spaces))
460
}

Read our documentation on viewing source code .

Loading