blob: cb0190fe0fbf96ca8f2089e87df2fed95a6faa35 [file] [log] [blame]
Hao Zhu62cdde52017-05-20 22:16:03 -04001#' Put a few rows of a table into one category
2#'
Hao Zhubd95bb22017-05-22 16:08:49 -04003#' @description Group a few rows in a table together under a label.
4#'
5#' @param kable_input Output of `knitr::kable()` with `format` specified
6#' @param group_label A character string for the name of the group
7#' @param start_row A numeric value that tells the function in which row the
8#' group starts. Note that the counting excludes header rows and other group
9#' labeling rows
10#' @param end_row A numeric value that tells the function in which row the group
11#' ends.
12#' @param label_row_css A character string for any customized css used for the
13#' labeling row. By default, the labeling row will have a solid black line
14#' underneath. Only useful for HTML documents.
15#' @param latex_gap_space A character value telling LaTeX how large the gap
16#' between the previous row and the group labeling row. Only useful for LaTeX
17#' documents.
18#'
Hao Zhu62cdde52017-05-20 22:16:03 -040019#' @export
Hao Zhud972e7f2017-05-22 13:27:15 -040020group_rows <- function(kable_input, group_label, start_row, end_row,
21 label_row_css = "border-bottom: 1px solid;",
22 latex_gap_space = "0.5em") {
23 if (!is.numeric(c(start_row, end_row))) {
24 stop("Start_row and end_row must be numeric position of rows (excluding",
25 "header rows and other group-title rows). ")
26 }
Hao Zhu62cdde52017-05-20 22:16:03 -040027 kable_format <- attr(kable_input, "format")
28 if (!kable_format %in% c("html", "latex")) {
29 message("Currently generic markdown table using pandoc is not supported.")
30 return(kable_input)
31 }
32 if (kable_format == "html") {
Hao Zhud972e7f2017-05-22 13:27:15 -040033 return(group_rows_html(kable_input, group_label, start_row, end_row,
34 label_row_css))
Hao Zhu62cdde52017-05-20 22:16:03 -040035 }
36 if (kable_format == "latex") {
Hao Zhud972e7f2017-05-22 13:27:15 -040037 return(group_rows_latex(kable_input, group_label, start_row, end_row,
38 latex_gap_space))
Hao Zhu62cdde52017-05-20 22:16:03 -040039 }
40}
41
Hao Zhud972e7f2017-05-22 13:27:15 -040042group_rows_html <- function(kable_input, group_label, start_row, end_row,
43 label_row_css) {
Hao Zhu62cdde52017-05-20 22:16:03 -040044 kable_attrs <- attributes(kable_input)
45 kable_xml <- read_xml(as.character(kable_input), options = "COMPACT")
46 kable_tbody <- xml_tpart(kable_xml, "tbody")
47
48 group_header_rows <- attr(kable_input, "group_header_rows")
49 group_seq <- seq(start_row, end_row)
50 if (!is.null(group_header_rows)) {
51 group_seq <- positions_corrector(group_seq, group_header_rows,
52 length(xml_children(kable_tbody)))
53 }
54
55 # Insert a group header row
56 starting_node <- xml_child(kable_tbody, group_seq[1])
57 kable_ncol <- length(xml_children(starting_node))
58 group_header_row_text <- paste0(
Hao Zhud972e7f2017-05-22 13:27:15 -040059 '<tr groupLength="', length(group_seq), '"><td colspan="', kable_ncol,
60 '" style="', label_row_css, '"><strong>', group_label,
61 "</strong></td></tr>"
Hao Zhu62cdde52017-05-20 22:16:03 -040062 )
63 group_header_row <- read_xml(group_header_row_text, options = "COMPACT")
64 xml_add_sibling(starting_node, group_header_row, .where = "before")
65
66 # add indentations to items
67 out <- structure(as.character(kable_xml), format = "html",
68 class = "knitr_kable")
69 attributes(out) <- kable_attrs
70 attr(out, "group_header_rows") <- c(attr(out, "group_header_rows"), group_seq[1])
71 out <- add_indent(out, positions = seq(start_row, end_row))
72 return(out)
73}
Hao Zhud972e7f2017-05-22 13:27:15 -040074
Hao Zhufc14c9b2017-05-22 14:03:22 -040075group_rows_latex <- function(kable_input, group_label, start_row, end_row,
76 gap_space) {
Hao Zhud972e7f2017-05-22 13:27:15 -040077 table_info <- magic_mirror(kable_input)
78 out <- kable_input
79
80 # Add group label
81 rowtext <- table_info$contents[start_row + 1]
82 if (table_info$booktabs) {
83 new_rowtext <- paste0(
84 "\\\\addlinespace[", gap_space, "]\n",
85 "\\\\multicolumn{", table_info$ncol, "}{l}{\\\\textbf{", group_label,
86 "}}\\\\\\\\\n",
87 rowtext
88 )
89 # last_row <- paste0(table_info$contents[end_row + 1], "\\\\\\\\")
90 # out <- sub(
91 # last_row,
92 # paste0(last_row, "\n\\\\addlinespace[", gap_space, "]"),
93 # out
94 # )
95 } else {
96 rowtext <- paste0("\\\\hline\n", rowtext)
97 new_rowtext <- paste0(
98 "\\\\hline\n\\\\multicolumn{", table_info$ncol, "}{l}{\\\\textbf{",
99 group_label, "}}\\\\\\\\\n", rowtext
100 )
101 }
102 out <- sub(rowtext, new_rowtext, out)
Hao Zhuf9aa4c42017-05-22 15:53:35 -0400103 attr(out, "original_kable_meta") <- table_info
Hao Zhud972e7f2017-05-22 13:27:15 -0400104 out <- add_indent(out, seq(start_row, end_row))
105 return(out)
106}