Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 1 | --- |
| 2 | title: "用kableExtra做牛*的表格" |
| 3 | author: "朱昊" |
| 4 | date: "`r Sys.Date()`" |
| 5 | output: |
| 6 | html_document: |
| 7 | theme: simplex |
| 8 | toc: true |
| 9 | toc_depth: 2 |
| 10 | toc_float: true |
| 11 | --- |
| 12 | |
Hao Zhu | b1caa27 | 2018-04-14 14:19:46 -0400 | [diff] [blame] | 13 | <img src="kableExtra.svg" align="right" alt="logo" width="80" height = "93" style = "border: none; float: right;"> |
| 14 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 15 | 说起来这包写了都一年了我还没写过中文文档,现在给大家补上。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 16 | |
Hao Zhu | b1caa27 | 2018-04-14 14:19:46 -0400 | [diff] [blame] | 17 | 另外这中文版我就不发CRAN了,要看的麻烦移步这包的文档网站[http://haozhu233.github.io/kableExtra/](http://haozhu233.github.io/kableExtra/)。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 18 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 19 | (因为我基本是在~~自由发挥~~重写一遍。。你们不要太去在意中文英文的不同哈。。。) |
| 20 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 21 | |
| 22 | # 简介 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 23 | `kableExtra`的目标是帮你搭建以及美化一些常用而又较为复杂的表格。这些表格有个特点,那就是用word 或者excel来做会极其简单,而要用一个编程语言去描述,尤其是对于一些LaTeX初心者(比如当年的我。。),往往会让人绝望。而现在,在这个包的帮助下,我希望你能用一种更为直觉的方式来创建你的表格,把更多的时间花在内容上。而那些排版之类的事情,就留给这个包吧。:) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 24 | |
Hao Zhu | 222cd7e | 2018-04-10 14:27:19 -0400 | [diff] [blame] | 25 | # 安装 |
| 26 | CRAN安装`install.packages("kableExtra")`不用我说,想尝鲜可以使用开发版。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 27 | ```r |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 28 | # install.packages("devtools") |
| 29 | devtools::install_github("haozhu233/kableExtra") |
| 30 | ``` |
Hao Zhu | 222cd7e | 2018-04-10 14:27:19 -0400 | [diff] [blame] | 31 | |
| 32 | # 第一步 |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 33 | ## 用`kable`生成HTML表格 |
| 34 | 首先要强调一下,`kable`这个function来自于R圈大佬谢益辉的`knitr`包。大致上说,`kable`可以生成三种格式的表格:`HTML`, `LaTeX` 和 `markdown`(默认)。`markdown`作为默认的格式完美契合`rmarkdown`本身,可却因为`markdown`表格本身功能上的限制,在很多情况下达不到我们的要求。因此,当你需要个性化你的表格时,你往往需要先让`kable`先帮你生成一个`HTML`的表格。在这份文档中,我们主要使用`mtcars`这个数据的前几列和几行数据来演示。 |
Hao Zhu | 222cd7e | 2018-04-10 14:27:19 -0400 | [diff] [blame] | 35 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 36 | ```{r} |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 37 | library(kableExtra) |
| 38 | dt <- mtcars[1:5, 1:6] |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 39 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 40 | kable(dt, "html") |
| 41 | ``` |
| 42 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 43 | 注意,如果你有好几个表格要去生成,与其在每一个kable里定义格式,不如在所有的事情开始之前定义一个全局的设置。这样的话,上面的语句就只需要打`kable(dt)`就可以了。 |
| 44 | |
| 45 | ```{r} |
| 46 | options(knitr.table.format = "html") |
| 47 | ``` |
| 48 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 49 | 当然,在今后的版本中(目前开发版),甚至这一步都可以被省略。今后,`kableExtra`将会自动根据你需要的情况帮你设好这个全局格式。这一步发生在你加载这个包的时候(`library(kableExtra)`),所以如果你不想要这个功能的话,可以在你加载`kableExtra`之前通过设置`options(kableExtra.auto_format = F)`来解决。 |
| 50 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 51 | ## bootstrap了解一下 |
Hao Zhu | b1caa27 | 2018-04-14 14:19:46 -0400 | [diff] [blame] | 52 | 如果你从没听过bootstrap的话,你应该去了解一下。简单来说,bootstrap是个开源的CSS库,可以用来很方便地美化HTML页面。也因此,bootstrap在RStudio的产品中被大量使用。你用rmarkdown和shiny生成出来的HTML文档和app都有加载。而这个包的HTML部分也提供了一些接口方便你快速实现一些bootstrap风的表格。 |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 53 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 54 | ```{r} |
| 55 | dt %>% |
| 56 | kable("html") %>% |
| 57 | kable_styling() |
| 58 | ``` |
| 59 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 60 | # 表格整体风格 |
| 61 | `kable_styling`提供了几种其他的方式来定制表格的整体风格。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 62 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 63 | ## Bootstrap的表格格式 |
| 64 | 如果你熟悉bootstrap,那么以下这些CSS类对你一定不陌生:`striped`, `bordered`, `hover`, `condensed` 以及 `responsive`. 不熟悉也没关系,你可以看看 [这里](http://getbootstrap.com/css/#tables)来了解。你可以通过`kable_styling`快速地把这些样式应用到你的表格里。比如,下面这个例子就是给表格加上斑马纹和悬浮效果。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 65 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 66 | ```{r} |
| 67 | kable(dt, "html") %>% |
| 68 | kable_styling(bootstrap_options = c("striped", "hover")) |
| 69 | ``` |
| 70 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 71 | 有些人觉得默认的bootstrap表格每行都太高了,这时候用上`condensed`会让内容显得更紧凑。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 72 | ```{r} |
| 73 | kable(dt, "html") %>% |
| 74 | kable_styling(bootstrap_options = c("striped", "hover", "condensed")) |
| 75 | ``` |
| 76 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 77 | `responsive`这选项可以让表格样式随屏幕宽度变化,更适合手机屏。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 78 | ```{r} |
| 79 | kable(dt, "html") %>% |
| 80 | kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive")) |
| 81 | ``` |
| 82 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 83 | ## “为啥我的表格这么宽啊?” |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 84 | “为啥我的表格这么宽”是一个`rmarkdown`新人常见问题。这其中的原因是,`bootstrap`把表格的宽度统一订成了100%的[容器](http://w3schools.wang/w3css/w3css_containers.html)宽。设计`bootstrap`的人原来想让你用他们的grid system来控制表格的宽度,可是当你在写`rmarkdown`的时候,难不成还想即兴来定义一串`<div>`?解决办法如下。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 85 | ```{r} |
| 86 | kable(dt, "html") %>% |
| 87 | kable_styling(bootstrap_options = "striped", full_width = F) |
| 88 | ``` |
| 89 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 90 | ## 表格位置 |
| 91 | 表格在页面中位置也是排版很重要的一块。注意,这只有在表格不是全屏宽的时候才有用(这是当然的啦。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 92 | ```{r} |
| 93 | kable(dt, "html") %>% |
| 94 | kable_styling(bootstrap_options = "striped", full_width = F, position = "left") |
| 95 | ``` |
| 96 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 97 | 除了常见的左中右,你还可以选择`float_left`和`float_right`。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 98 | ```{r} |
| 99 | kable(dt, "html") %>% |
| 100 | kable_styling(bootstrap_options = "striped", full_width = F, position = "float_right") |
| 101 | ``` |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 102 | 滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。 古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。古今多少事,都付笑谈中。滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。 一壶浊酒喜相逢。 古今多少事,都付笑谈中。 |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 103 | |
| 104 | |
| 105 | ## 字体大小 |
| 106 | 如题,当你的表格过大时,你可以调调字体大小。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 107 | ```{r} |
| 108 | kable(dt, "html") %>% |
| 109 | kable_styling(bootstrap_options = "striped", font_size = 7) |
| 110 | ``` |
| 111 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 112 | # 列与行的格式 |
| 113 | ## 列 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 114 | `column_spec`如其名,可以帮你定义某一列或者几列的样式,比如宽度,字体颜色,加粗,斜体等。列的宽度其实尤为重要,这样如果你的表格里有一串巨长的文字,它的格式不会一下被打乱。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 115 | |
| 116 | ```{r} |
| 117 | text_tbl <- data.frame( |
| 118 | Items = c("Item 1", "Item 2", "Item 3"), |
| 119 | Features = c( |
| 120 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vehicula tempor ex. Morbi malesuada sagittis turpis, at venenatis nisl luctus a. ", |
| 121 | "In eu urna at magna luctus rhoncus quis in nisl. Fusce in velit varius, posuere risus et, cursus augue. Duis eleifend aliquam ante, a aliquet ex tincidunt in. ", |
| 122 | "Vivamus venenatis egestas eros ut tempus. Vivamus id est nisi. Aliquam molestie erat et sollicitudin venenatis. In ac lacus at velit scelerisque mattis. " |
| 123 | ) |
| 124 | ) |
| 125 | |
| 126 | kable(text_tbl, "html") %>% |
| 127 | kable_styling(full_width = F) %>% |
| 128 | column_spec(1, bold = T, border_right = T) %>% |
| 129 | column_spec(2, width = "30em", background = "yellow") |
| 130 | ``` |
| 131 | |
| 132 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 133 | ## 行 |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 134 | `row_spec`和`column_spec`差不多,除了没有列宽。注意,当你数第几行的时候,你不需要考虑表头和你通过`pack_rows`添加的那些行,就数那些原生的“内容”行就行。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 135 | |
| 136 | ```{r} |
| 137 | kable(dt, "html") %>% |
| 138 | kable_styling("striped", full_width = F) %>% |
| 139 | column_spec(5:7, bold = T) %>% |
| 140 | row_spec(3:5, bold = T, color = "white", background = "#D7261E") |
| 141 | ``` |
| 142 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 143 | ### 表头的那行 |
| 144 | 只需要说`row_spec(0, ...)`就可以了。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 145 | ```{r} |
| 146 | kable(dt, format = "html") %>% |
| 147 | kable_styling("striped", full_width = F) %>% |
| 148 | row_spec(0, angle = -45) |
| 149 | ``` |
| 150 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 151 | # 格子的格式 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 152 | `cell_spec` 和之前说的两个`spec`不一样,你应该在把你的数据放进`kable`之前使用它,就像接下来的例子。你可以很容易地在`dplyr`的pipeline里加上一截`cell_spec`。注意,因为你用`cell_spec`生成的是直接的`HTML`和`LaTeX`,你需要在`kable`里加上`escape = FALSE`。同时,你需要告诉`cell_spec`你到底需要`HTML`还是`LaTeX`。而在今后版本的`kableExtra`里,因为全局的表格格式已经被自动设好了,你就不需要做这一步了。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 153 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 154 | ## `cell_spec`和`ifelse` |
| 155 | `cell_spec`和`ifelse`结合会让表格里的数据的可视度一下子高很多。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 156 | ```{r, message=FALSE, warning=FALSE} |
| 157 | library(dplyr) |
| 158 | mtcars[1:10, 1:2] %>% |
| 159 | mutate( |
| 160 | car = row.names(.), |
| 161 | # You don't need format = "html" if you have ever defined options(knitr.table.format) |
| 162 | mpg = cell_spec(mpg, "html", color = ifelse(mpg > 20, "red", "blue")), |
| 163 | cyl = cell_spec(cyl, "html", color = "white", align = "c", angle = 45, |
| 164 | background = factor(cyl, c(4, 6, 8), |
| 165 | c("#666666", "#999999", "#BBBBBB"))) |
| 166 | ) %>% |
| 167 | select(car, mpg, cyl) %>% |
| 168 | kable("html", escape = F) %>% |
| 169 | kable_styling("striped", full_width = F) |
| 170 | ``` |
| 171 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 172 | ## 给你的表格加上Viridis Color |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 173 | 这包还带了几个`cell_spec`的辅助型方程,包括 `spec_color`, `spec_font_size` 和 `spec_angle`. 他们可以帮你把数据变成相应的颜色,字体大小和角度。其中最有意思的是那个颜色,这里用了[viridis color](https://CRAN.R-project.org/package=viridisLite)这个色板. 合理使用的话几乎可以用表格做出类似热图的可视化。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 174 | |
| 175 | ```{r} |
| 176 | iris[1:10, ] %>% |
| 177 | mutate_if(is.numeric, function(x) { |
| 178 | cell_spec(x, "html", bold = T, |
| 179 | color = spec_color(x, end = 0.9), |
| 180 | font_size = spec_font_size(x)) |
| 181 | }) %>% |
| 182 | mutate(Species = cell_spec( |
| 183 | Species, "html", color = "white", bold = T, |
| 184 | background = spec_color(1:10, end = 0.9, option = "A", direction = -1) |
| 185 | )) %>% |
| 186 | kable("html", escape = F, align = "c") %>% |
| 187 | kable_styling("striped", full_width = F) |
| 188 | ``` |
| 189 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 190 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 191 | ## 普通文本的格式 |
| 192 | 其实你也可以用`cell_spec`或者`text_spec`去定义普通文字的样式。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 193 | |
| 194 | ```{r} |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 195 | sometext <- strsplit("人群中突然钻出一个光头", "")[[1]] |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 196 | text_formatted <- paste( |
| 197 | text_spec(sometext, "html", color = spec_color(1:length(sometext), end = 0.9), |
| 198 | font_size = spec_font_size(1:length(sometext), begin = 5, end = 20)), |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 199 | collapse = "") |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 200 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 201 | ``` |
| 202 | `r text_formatted` |
| 203 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 204 | ## Tooltip 悬浮提示框 |
| 205 | 你可以通过`cell_spec`相对简单地添加悬浮提示框. 举个例子,`text_spec("tooltip", color = "red", tooltip = "Hello World")` 会生成 `r text_spec("Hover over me", color = "red", tooltip = "Hello World")`。注意HTML原生的提示框非常慢,你可能会想用`bootstrap`的javascript版的。如果你想这么做的话,你需要把接下来的这段代码放在你的rmarkdown文本的任何地方。需要注意的是,如果你和这个文档一样使用了这种目录在侧面的格式,你就没办法使用这个功能。原因在于这个和`jqueryui`的`tooltip`互相冲突。这种情况下,你可能会想试试我下面说的`popover`。这两个差不多。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 206 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 207 | ``` |
| 208 | <script> |
| 209 | $(document).ready(function(){ |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 210 | $('[data-toggle="tooltip"]').tooltip(); |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 211 | }); |
| 212 | </script> |
| 213 | ``` |
| 214 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 215 | ## Popover Message 有头的悬浮弹出提示框 |
| 216 | 和之前一样的设定,区别在于你可以给`popover`的小框加一个标题。不加的话,和上面的功能基本一样。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 217 | |
| 218 | ``` |
| 219 | <script> |
| 220 | $(document).ready(function(){ |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 221 | $('[data-toggle="popover"]').popover(); |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 222 | }); |
| 223 | </script> |
| 224 | ``` |
| 225 | |
| 226 | <script> |
| 227 | $(document).ready(function(){ |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 228 | $('[data-toggle="popover"]').popover(); |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 229 | }); |
| 230 | </script> |
| 231 | |
| 232 | ```{r} |
| 233 | popover_dt <- data.frame( |
| 234 | position = c("top", "bottom", "right", "left"), |
| 235 | stringsAsFactors = FALSE |
| 236 | ) |
| 237 | popover_dt$`Hover over these items` <- cell_spec( |
| 238 | paste("Message on", popover_dt$position), # Cell texts |
| 239 | popover = spec_popover( |
| 240 | content = popover_dt$position, |
| 241 | title = NULL, # title will add a Title Panel on top |
| 242 | position = popover_dt$position |
| 243 | )) |
| 244 | kable(popover_dt, "html", escape = FALSE) %>% |
| 245 | kable_styling("striped", full_width = FALSE) |
| 246 | ``` |
| 247 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 248 | ## 链接 |
| 249 | 你可以给文字添加一个链接`text_spec("Google", link = "https://google.com")`: `r text_spec("Google", link = "https://google.com")`。这里有一个利用加链接让`popover`悬浮框本来的文本更加明显的小技巧 `text_spec("Hover on me", link = "javascript:void(0)", popover = "Hello")`: `r text_spec("Hover on me", link = "javascript:void(0)", popover = "Hello")` |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 250 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 251 | ## 同时使用`kableExtra`和`formattable` |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 252 | 如果你也喜欢[`formattable`](https://github.com/renkun-ken/formattable)的话,你其实可以将`formattable`和`kableExtra`用在一起,灰常酷炫。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 253 | ```{r, message = FALSE, warning=FALSE} |
| 254 | library(formattable) |
| 255 | mtcars[1:5, 1:4] %>% |
| 256 | mutate( |
| 257 | car = row.names(.), |
| 258 | mpg = color_tile("white", "orange")(mpg), |
| 259 | cyl = cell_spec(cyl, "html", angle = (1:5)*60, |
| 260 | background = "red", color = "white", align = "center"), |
| 261 | disp = ifelse(disp > 200, |
| 262 | cell_spec(disp, "html", color = "red", bold = T), |
| 263 | cell_spec(disp, "html", color = "green", italic = T)), |
| 264 | hp = color_bar("lightgreen")(hp) |
| 265 | ) %>% |
| 266 | select(car, everything()) %>% |
| 267 | kable("html", escape = F) %>% |
| 268 | kable_styling("hover", full_width = F) %>% |
| 269 | column_spec(5, width = "3cm") %>% |
| 270 | add_header_above(c(" ", "Hello" = 2, "World" = 2)) |
| 271 | ``` |
| 272 | |
| 273 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 274 | # 行组和列组 |
| 275 | ## 列组 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 276 | 我们在Word里做表格时,要想表示两个列同属一个分类,我们会在这两列的上面再加一行,画条横线,写上名字。基本上`add_header_above`就是被设计来做这事的。在使用这个方程时,你需要给他一个**`named vector`**(划重点)。这个`named vector`的本身数值是所有列的 span值,而具体的文字则在names里(没看懂我在说啥的,请参考下面的例子)。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 277 | ```{r} |
| 278 | kable(dt, "html") %>% |
| 279 | kable_styling("striped") %>% |
| 280 | add_header_above(c(" " = 1, "Group 1" = 2, "Group 2" = 2, "Group 3" = 2)) |
| 281 | ``` |
| 282 | |
Hao Zhu | 9ac3e38 | 2018-04-12 18:56:32 -0400 | [diff] [blame] | 283 | 事实上,你甚至可以一层一层继续往上加下去。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 284 | ```{r} |
| 285 | kable(dt, "html") %>% |
| 286 | kable_styling(c("striped", "bordered")) %>% |
| 287 | add_header_above(c(" ", "Group 1" = 2, "Group 2" = 2, "Group 3" = 2)) %>% |
| 288 | add_header_above(c(" ", "Group 4" = 4, "Group 5" = 2)) %>% |
| 289 | add_header_above(c(" ", "Group 6" = 6)) |
| 290 | ``` |
| 291 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 292 | ## 行组 |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 293 | 我们一般做表格时,想表示几行同属一类一般有两种方式,其一是新插入一行大类的名称,然后再给那几行小的加上缩进。其二是在左边再加上一列,通过合并相印的行来表示所属的意思。相对应的,在`kableExtra`里,第一种方法可以用`pack_rows`实现,而第二种则可以用`collapse_row`。 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 294 | |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 295 | ### `pack_rows` |
| 296 | 我们先说`pack_rows`,请看下面这个例子。 |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 297 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 298 | ```{r} |
| 299 | kable(mtcars[1:10, 1:6], "html", caption = "Group Rows") %>% |
| 300 | kable_styling("striped", full_width = F) %>% |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 301 | pack_rows("Group 1", 4, 7) %>% |
| 302 | pack_rows("Group 2", 8, 10) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 303 | ``` |
| 304 | |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 305 | 另一种使用`pack_rows`的方法是提供一个目录,用法和`add_header_above`相同。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 306 | ```{r, eval = F} |
| 307 | # Not evaluated. This example generates the same table as above. |
| 308 | kable(mtcars[1:10, 1:6], "html", caption = "Group Rows") %>% |
| 309 | kable_styling("striped", full_width = F) %>% |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 310 | pack_rows(index = c(" " = 3, "Group 1" = 4, "Group 2" = 3)) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 311 | ``` |
| 312 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 313 | 如果你熟悉CSS,你可以自己定义标签行的样式。 |
| 314 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 315 | ```{r} |
| 316 | kable(dt, "html") %>% |
| 317 | kable_styling("striped", full_width = F) %>% |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 318 | pack_rows("Group 1", 3, 5, label_row_css = "background: repeating-linear-gradient(45deg, #d9230f, #d9230f 10px, #f96352 10px, #f96352 20px); color: #fff;") |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 319 | ``` |
| 320 | |
Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame^] | 321 | 说起来,`pack_rows`本来叫`group_rows`,可是`dplyr`0.8加了个同名的function,所以起了个小名,这样大家用起来方便些。 |
| 322 | |
| 323 | (白学现场:明明都是我先来的) |
| 324 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 325 | ### 行的缩进 |
| 326 | 有时候只添加缩进就可以变的很有用,这时候你需要`add_indent`。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 327 | ```{r} |
| 328 | kable(dt, "html") %>% |
| 329 | kable_styling("striped", full_width = F) %>% |
| 330 | add_indent(c(1, 3, 5)) |
| 331 | ``` |
| 332 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 333 | ### 合并行 |
| 334 | `collapse_rows` 做的就是我们之前说的第二种在表格内表示所属关系的方法。请看下面的例子,第一二两列所有重复的内容都被自动合并了。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 335 | |
| 336 | ```{r} |
| 337 | collapse_rows_dt <- data.frame(C1 = c(rep("a", 10), rep("b", 5)), |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 338 | C2 = c(rep("c", 7), rep("d", 3), rep("c", 2), rep("d", 3)), |
| 339 | C3 = 1:15, |
| 340 | C4 = sample(c(0,1), 15, replace = TRUE)) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 341 | kable(collapse_rows_dt, "html", align = "c") %>% |
| 342 | kable_styling(full_width = F) %>% |
| 343 | column_spec(1, bold = T) %>% |
| 344 | collapse_rows(columns = 1:2) |
| 345 | ``` |
| 346 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 347 | # 表格注脚 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 348 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 349 | 给表格添加注脚也是一个很常见的操作。在`kableExtra`里对应的是`footnote`方程。在这里,你可以使用四套编号体系:无编号`general`,数字`number`,字母`alphabet`和特殊符号`symbol`。注意,特殊符号我只定义了20个,因为一般你给表格加的注脚也不会有那么多。正如下面这个例子,你可以选择只用其中一种或者同时使用几种。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 350 | |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 351 | ```{r} |
| 352 | kable(dt, "html", align = "c") %>% |
| 353 | kable_styling(full_width = F) %>% |
| 354 | footnote(general = "Here is a general comments of the table. ", |
| 355 | number = c("Footnote 1; ", "Footnote 2; "), |
| 356 | alphabet = c("Footnote A; ", "Footnote B; "), |
| 357 | symbol = c("Footnote Symbol 1; ", "Footnote Symbol 2") |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 358 | ) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 359 | ``` |
| 360 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 361 | 要是想要修改每一类的标题的话,你可以使用那些`***_title`变量. 你还可以通过 `footnote_order`来更改他们的顺序. 你甚至可以通过`footnote_as_chunk`,让备注们以一个段落的方式显示. |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 362 | |
| 363 | ```{r} |
| 364 | kable(dt, "html", align = "c") %>% |
| 365 | kable_styling(full_width = F) %>% |
| 366 | footnote(general = "Here is a general comments of the table. ", |
| 367 | number = c("Footnote 1; ", "Footnote 2; "), |
| 368 | alphabet = c("Footnote A; ", "Footnote B; "), |
| 369 | symbol = c("Footnote Symbol 1; ", "Footnote Symbol 2"), |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 370 | general_title = "备注: ", number_title = "备注233: ", |
| 371 | alphabet_title = "备注666: ", symbol_title = "备注888: ", |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 372 | footnote_as_chunk = T |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 373 | ) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 374 | ``` |
| 375 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 376 | 若是想在表格内部添加注释的小字的话,你需要使用那些`footnote_mark_***()`方程. 和 `cell_spec`一样,你需要告诉他们你想要的格式(在今后的版本里你不需要了)同时在使用`kable`的时候往里加上`escape=F`。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 377 | |
| 378 | ```{r} |
| 379 | dt_footnote <- dt |
| 380 | names(dt_footnote)[2] <- paste0(names(dt_footnote)[2], |
| 381 | footnote_marker_symbol(1)) |
| 382 | row.names(dt_footnote)[4] <- paste0(row.names(dt_footnote)[4], |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 383 | footnote_marker_alphabet(1)) |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 384 | kable(dt_footnote, "html", align = "c", |
| 385 | # Remember this escape = F |
| 386 | escape = F) %>% |
| 387 | kable_styling(full_width = F) %>% |
| 388 | footnote(alphabet = "Footnote A; ", |
| 389 | symbol = "Footnote Symbol 1; ", |
| 390 | alphabet_title = "Type II: ", symbol_title = "Type III: ", |
| 391 | footnote_as_chunk = T) |
| 392 | ``` |
| 393 | |
Hao Zhu | 6f2a017 | 2018-04-13 17:03:40 -0400 | [diff] [blame] | 394 | # HTML独占功能 |
| 395 | ## 框住你的表格 |
| 396 | 若你的表格过大而你又不想随便缩字体大小,你可以用`scroll_box`把它放进一个盒子,这样用户可以自己选择想看的位置。下面的例子里我同时定义了盒子的高度和宽度,但你其实可以根据你的需求,只定义其中一个。需要注意的是,如果你同时需要打印这个表格,那你最好不要使用这个`scroll_box`。因为在打印的时候,被打印的将不会是整个表格,而会是到时候你屏幕上显示的部分。 |
Hao Zhu | 5e4dd50 | 2018-04-05 12:01:58 -0400 | [diff] [blame] | 397 | |
| 398 | ```{r} |
| 399 | kable(cbind(mtcars, mtcars), "html") %>% |
| 400 | kable_styling() %>% |
| 401 | scroll_box(width = "500px", height = "200px") |
| 402 | ``` |
Hao Zhu | f0f1924 | 2018-05-11 17:50:46 -0400 | [diff] [blame] | 403 | |
| 404 | 另外,除了一个具体的宽度或者高度,你也可以选择百分比哦。比如`width="100%"`就很实用。另外不喜欢默认的灰色直角框,你也可以通过定义`box_css`把消掉或者替换掉。 |
| 405 | ```{r} |
| 406 | kable(cbind(mtcars, mtcars)[1:5, ], "html") %>% |
| 407 | kable_styling() %>% |
| 408 | scroll_box(width = "100%", box_css = ' |
| 409 | padding: 15px; border: 15px solid transparent; |
| 410 | background: linear-gradient(white,white), repeating-linear-gradient(45deg, #d9230f, #d9230f 10px, #f96352 10px, #f96352 20px); |
| 411 | background-clip: padding-box, border-box;') |
| 412 | ``` |
Hao Zhu | 6107f37 | 2018-05-21 00:23:26 -0400 | [diff] [blame] | 413 | |
| 414 | ## 保存HTML表格 |
| 415 | 一般来说rmarkdown够用了,但有时候生成很多表格时候,可以考虑`save_kable()`. 如果把`self_contained`设为`F`的话,css文件会被单独放进一个文件夹(而不是被打包进网页),可以节省空间。 |
| 416 | ```{r, eval=FALSE} |
| 417 | kable(mtcars) %>% |
| 418 | kable_styling() %>% |
| 419 | save_kable(file = "table1.html", self_contained = T) |
| 420 | ``` |
| 421 | |
| 422 | # 和别的包的合作 |
| 423 | `kable()`简单的格式意味着将由其他的包生成的HTML或者LaTeX转换成`kable`并不是一件难事。 |
Hao Zhu | ccf9bf8 | 2018-05-21 01:09:16 -0400 | [diff] [blame] | 424 | |
Hao Zhu | 6107f37 | 2018-05-21 00:23:26 -0400 | [diff] [blame] | 425 | ## `tables` |
| 426 | 最新版的`tables`中加个一个`toKable()`。 |