blob: aac4b9b48510f5c29d45730f3b3603fc9e09d9f8 [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
Hao Zhufdff6f42020-08-09 14:38:10 -04004#' @param columns A numeric value or vector indicating in which column(s) rows
5#' need to be removed
Dan Chaltiel075db092020-08-03 22:18:33 +02006#'
7#' @export
8#'
9#' @examples
Hao Zhufdff6f42020-08-09 14:38:10 -040010#' remove_column(kable(mtcars), 1)
Dan Chaltiel9e83d8f2020-08-03 22:46:35 +020011remove_column <- function (kable_input, columns) {
Hao Zhufdff6f42020-08-09 14:38:10 -040012 if (is.null(columns)) return(kable_input)
Dan Chaltiel075db092020-08-03 22:18:33 +020013 kable_format <- attr(kable_input, "format")
14 if (!kable_format %in% c("html", "latex")) {
Hao Zhufdff6f42020-08-09 14:38:10 -040015 warning("Please specify format in kable. kableExtra can customize",
16 " either HTML or LaTeX outputs. See ",
17 "https://haozhu233.github.io/kableExtra/ for details.")
Dan Chaltiel075db092020-08-03 22:18:33 +020018 return(kable_input)
19 }
Hao Zhufdff6f42020-08-09 14:38:10 -040020
21 columns <- sort(unique(columns))
Dan Chaltiel075db092020-08-03 22:18:33 +020022 if (kable_format == "html") {
23 return(remove_column_html(kable_input, columns))
24 } else if (kable_format == "latex") {
25 stop("Removing columns was not implemented for latex kables yet")
26 }
27}
28
29remove_column_html <- function (kable_input, columns) {
30 kable_attrs <- attributes(kable_input)
31 kable_xml <- kable_as_xml(kable_input)
32 kable_tbody <- xml_tpart(kable_xml, "tbody")
33 kable_thead <- xml_tpart(kable_xml, "thead")
Hao Zhufdff6f42020-08-09 14:38:10 -040034
35 group_header_rows <- attr(kable_input, "group_header_rows")
36 all_contents_rows <- seq(1, length(xml_children(kable_tbody)))
37
38 if (!is.null(group_header_rows)) {
39 warning("It's recommended to use remove_column after add_header_above.",
40 "Right now some column span numbers might not be correct. ")
41 all_contents_rows <- all_contents_rows[!all_contents_rows %in%
42 group_header_rows]
43 }
44
45 collapse_matrix <- attr(kable_input, "collapse_matrix")
46 collapse_columns <- NULL
47 if (!is.null(collapse_matrix)) {
48 collapse_columns <- sort(as.numeric(sub("x", "",
49 names(collapse_matrix))))
50 collapse_columns_origin <- collapse_columns
51 }
52
53 while (length(columns) > 0) {
54 xml2::xml_remove(xml2::xml_child(
55 xml2::xml_child(kable_thead, xml2::xml_length(kable_thead)),
56 columns[1]))
57 if (length(collapse_columns) != 0 && collapse_columns[1] <= columns[1]){
58 if (columns[1] %in% collapse_columns) {
59 column_span <- collapse_matrix[[paste0('x', columns[1])]]
60 non_skip_rows <- column_span != 0
61 collapse_columns <- collapse_columns[
62 collapse_columns != columns[1]
63 ] - 1
64 } else {
65 non_skip_rows <- rep(TRUE, length(all_contents_rows))
66 }
67 prior_col <- which(collapse_columns_origin < columns[1])
68 for (i in all_contents_rows[non_skip_rows]) {
69 if (length(prior_col) == 0) {
70 pos_adj <- 0
71 } else {
72 pos_adj <- sum(collapse_matrix[i, prior_col] == 0)
73 }
74 target_cell <- xml2::xml_child(
75 xml2::xml_child(kable_tbody, i),
76 columns[1] - pos_adj)
77 xml2::xml_remove(target_cell)
78 }
79 } else {
80 for (i in all_contents_rows) {
81 target_cell <- xml2::xml_child(
82 xml2::xml_child(kable_tbody, i),
83 columns[1])
84 xml2::xml_remove(target_cell)
Dan Chaltielc0d30292020-08-04 00:17:24 +020085 }
86 }
Hao Zhufdff6f42020-08-09 14:38:10 -040087 # not very efficient but for finite task it's probably okay
88 columns <- (columns - 1)[-1]
Dan Chaltielc0d30292020-08-04 00:17:24 +020089 }
Hao Zhufdff6f42020-08-09 14:38:10 -040090
91 # head_row <- xml2::xml_child(kable_thead, xml2::xml_length(kable_thead))
92 # ncols <- xml2::xml_length(head_row)
93 # body_nrows <- xml2::xml_length(kable_tbody)
94 #
95 # rowspan = matrix(1, nrow = body_nrows, ncol=ncols)
96 # for(i in 1:body_nrows){
97 # target_row <- xml2::xml_child(kable_tbody, i)
98 # target_ncols <- xml2::xml_length(target_row)
99 # for(j in 1:target_ncols){
100 # target_cell <- xml2::xml_child(target_row, j)
101 # span <- as.numeric(xml2::xml_attr(target_cell, "rowspan"))
102 # span[is.na(span)] <- 0
103 # if(span>0){
104 # rowspan[i,j]=1
105 # rowspan[i+seq(from=1, to=span-1),j]=0
106 # }
107 # }
108 # }
109 #
110 # for(i in 1:body_nrows){
111 # target_row <- xml2::xml_child(kable_tbody, i)
112 # for(j in rev(columns)){
113 # target_cell <- xml2::xml_child(target_row, j)
114 # if(rowspan[i,j]==1)
115 # xml2::xml_remove(target_cell)
116 # }
117 # }
118 #
119 # for(j in columns){
120 # target_cell_head <- xml2::xml_child(head_row, j)
121 # xml2::xml_remove(target_cell_head)
122 # }
Dan Chaltiel075db092020-08-03 22:18:33 +0200123 out <- as_kable_xml(kable_xml)
124 attributes(out) <- kable_attrs
Hao Zhufdff6f42020-08-09 14:38:10 -0400125 if (!"kableExtra" %in% class(out))
Dan Chaltiel075db092020-08-03 22:18:33 +0200126 class(out) <- c("kableExtra", class(out))
Hao Zhufdff6f42020-08-09 14:38:10 -0400127
Dan Chaltiel075db092020-08-03 22:18:33 +0200128 return(out)
129}