blob: 828edaecb4b8152fb86712a9fd608ae63b727e6e [file] [log] [blame]
Dan Chaltiel075db092020-08-03 22:18:33 +02001#' Remove columns
2#'
3#' @param kable_input Output of [knitr::kable()] with format specified
4#' @param columns A numeric value or vector indicating in which column(s) rows need to be removed
5#'
6#' @export
7#'
8#' @examples
9#' mtcars %>%
10#' kable() %>%
11#' remove_column(2:3)
Dan Chaltiel9e83d8f2020-08-03 22:46:35 +020012remove_column <- function (kable_input, columns) {
Dan Chaltiel0a0f7922020-08-05 09:11:23 +020013 if(is.null(columns)) return(kable_input)
Dan Chaltiel075db092020-08-03 22:18:33 +020014 kable_format <- attr(kable_input, "format")
15 if (!kable_format %in% c("html", "latex")) {
16 warning("Please specify format in kable. kableExtra can customize either ",
17 "HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ ",
18 "for details.")
19 return(kable_input)
20 }
21 if (kable_format == "html") {
22 return(remove_column_html(kable_input, columns))
23 } else if (kable_format == "latex") {
24 stop("Removing columns was not implemented for latex kables yet")
25 }
26}
27
28remove_column_html <- function (kable_input, columns) {
29 kable_attrs <- attributes(kable_input)
30 kable_xml <- kable_as_xml(kable_input)
31 kable_tbody <- xml_tpart(kable_xml, "tbody")
32 kable_thead <- xml_tpart(kable_xml, "thead")
33
34 cell_topleft <- xml2::xml_child(kable_thead, 1) %>%
35 xml2::xml_child(1) %>%
36 xml2::xml_text() %>%
37 stringr::str_trim()
38 has_rownames <- cell_topleft==""
Dan Chaltiel075db092020-08-03 22:18:33 +020039
Dan Chaltielc0d30292020-08-04 00:17:24 +020040 head_row <- xml2::xml_child(kable_thead, 1)
41 ncols <- xml2::xml_length(head_row)
42 body_nrows <- xml2::xml_length(kable_tbody)
43
44 rowspan = matrix(1, nrow = body_nrows, ncol=ncols)
45 for(i in 1:body_nrows){
46 target_row <- xml2::xml_child(kable_tbody, i)
47 target_ncols <- xml2::xml_length(target_row)
48 for(j in 1:target_ncols){
Dan Chaltiel075db092020-08-03 22:18:33 +020049 target_cell <- xml2::xml_child(target_row, j)
Dan Chaltielc0d30292020-08-04 00:17:24 +020050 span = as.numeric(xml2::xml_attr(target_cell, "rowspan")) %>% replace_na(0)
51 if(span>0){
52 rowspan[i,j]=1
53 rowspan[i+seq(from=1, to=span-1),j]=0
54 }
55 }
56 }
57
58 for(i in 1:body_nrows){
59 target_row <- xml2::xml_child(kable_tbody, i)
Dan Chaltielf8f06162020-08-04 00:33:55 +020060 for(j in rev(columns)){
Dan Chaltielc0d30292020-08-04 00:17:24 +020061 target_cell <- xml2::xml_child(target_row, j)
62 if(rowspan[i,j]==1)
Dan Chaltiel075db092020-08-03 22:18:33 +020063 xml2::xml_remove(target_cell)
64 }
65 }
Dan Chaltielc0d30292020-08-04 00:17:24 +020066
Dan Chaltiel075db092020-08-03 22:18:33 +020067 for(j in columns){
Dan Chaltielc0d30292020-08-04 00:17:24 +020068 target_cell_head <- xml2::xml_child(head_row, j)
Dan Chaltiel075db092020-08-03 22:18:33 +020069 xml2::xml_remove(target_cell_head)
70 }
71 out <- as_kable_xml(kable_xml)
72 attributes(out) <- kable_attrs
73 if (!"kableExtra" %in% class(out))
74 class(out) <- c("kableExtra", class(out))
75
76 return(out)
77}