R 中的交互式表格包:
2022-11-25
R 中的交互式表格包:
1.丰富数据元素
往表格里插入 Unicode 字符、图片、超链接、字体图标(icon)、迷你图(sparkline)等。
2.丰富表格元素
多行表头、表格标题、表格脚注。
3.设置静态样式
自定义样式、formatStyle 函数、引入 JS。
library(DT) set.seed(2022) data <- data.frame( type1 = sort(rep(LETTERS[1:20], 2)), type2 = rep(c('NO', 'YES'), 20), value1 = sample(200:2000, 40), value2 = sample(200:2000, 40), level = sample(1:5, 40, replace = TRUE) ) # 设置全局选项 options(DT.options = list(dom = 'lftp')) datatable(data)
datatable(data) |> formatCurrency( columns = c('value1', 'value2'), currency = '\u2714', # 代表 ✔ before = FALSE, digits = 2, rows = c(1:2)) |> formatString( columns = 2, prefix = '¥', suffix = '\u2716', # 代表 ✖ rows = seq( from = 1, to = nrow(data), by = 2))
<img class="自定义 css 样式" src="图片链接" alt="图片alt">
# 图片名字 imgvalue <- c(rep('China', 2), rep('USA', 2)) imgdata <- cbind(data, imgvalue) # 由于图片名字在表中第6列,所以列渲染时写row[6] datatable(imgdata, options = list( pageLength = 5, columnDefs = list( list(targets = 1, render = JS(" function(data, type, row, meta) {return '<img src=\"https://yuanfan.rbind.io/images/' + row[6] + '.png\" />' + data}")), list(targets = 6, visible = FALSE))))
<img src="https://yuanfan.rbind.io/images/imgvalue.png">
datatable(imgdata, options = list( columnDefs = list( list(targets = 1, render = JS(" function(data, type, row, meta) {return '<img class=\"team-flag\" src=\"https://yuanfan.rbind.io/images/' + row[6] + '.png\" />' +'<span class=\"team-name\">'+data +'<span/><span class=\"team-record\">' + row[5] + 'level'+'<span/>' }")), list(targets = 6, visible = FALSE))))
<img>
元素里有多余空格。<img class = "team-flag" src = "https://yuanfan.rbind.io/images/imgvalue.png">
<span class = "team-name"> type1 </span>
<span class = "team-record"> level 'level'</span>
<a class="自定义 css 样式" href="超链接地址">超链接显示名</a>
hrefvalue = c(rep("https://yufree.cn/cn/", 2), rep("https://xiangyun.rbind.io/post/", 2)) hrefdata <- cbind(data, hrefvalue) datatable(hrefdata, options = list(columnDefs = list( list( targets = 2, render = JS( "function(data, type, row, meta) { return '<a href=' + row[6] + '>' + data + '</a>'}")), list(targets = 6, visible = FALSE) )))
row[6]
表示取数据中第6列中的值。icon()
可以方便地从字体图标库 Font Awesome 或 Bootstrap Glyphicons 引入小图标。其中,Font Awesome 库在 R 中也有对应的 R 包 fontawesome。library(fontawesome) library(data.table) icon1data <- as.data.table(data) icon1data <- icon1data[, ':='(icon1 = ifelse( type2 == "YES", fontawesome::fa(name = "thumbs-up"), fontawesome::fa(name = "thumbs-down") ))] datatable(icon1data, escape = FALSE)
icon2data <- as.data.table(data) # icon2data$level <- sapply(icon2data$level , # function(level) { # paste( # rep(fontawesome::fa(name = "heart"),level), # collapse = "") # }) icon2data$level <- strrep(fontawesome::fa(name = "heart"), icon2data$level) datatable(icon2data, escape = FALSE)
library(sparkline) dt <- as.data.table(data) spark_html <- function(...) { as.character(htmltools::as.tags(sparkline(..., height = 100, width=100)))} dt.DT1 <- dt[, .( # 部分参数含义见备注(按P键)。 '面积图' = spark_html(value1, type = "line"), '柱状图' = spark_html(value1, type = "bar"), '折线图' = spark_html(value1, type = "line", lineColor = "red", fillColor = FALSE), '柱状图2' = spark_html(value1, type = "bar", barColor = "green"), '箱图' = spark_html(value1, type = "box") ), keyby = .(type2)] datatable(dt.DT1, escape = FALSE, options = list(dom = 't')) |> spk_add_deps()
dt.DT2 <- dt[, .('饼图' = spark_html(value1, type = "pie", sliceColors = c("red", "green"), offset = 90)), keyby = .(type1)] datatable(dt.DT2, escape = FALSE, options = list(pageLength=2, dom = 'tp', # 每次分页重新渲染,不加这个的话只有第一页有图 drawCallback = JS('function(s) { HTMLWidgets.staticRender(); }') )) |> spk_add_deps()
dt.DT <- dt[, .( "两条折线" = as.character(htmltools::as.tags(spk_composite( sparkline(value1, type = "line", fillColor = FALSE, lineColor = 'red', width = 300, height = 100), sparkline(value2, type = "line", fillColor = FALSE, lineColor = 'green', width = 300, height = 100)))) ), keyby = .(type2)] datatable(dt.DT, escape = FALSE, options = list(dom = 't')) |> spk_add_deps()
sparkline()
一起写入 spk_composite()
中。datatable(data, caption = '一个表格的标题') datatable( data, options = list(dom = 'tp', pageLength = 3), caption = htmltools::tags$caption( style = 'caption-side: top; text-align: center;', htmltools::h5(class = 'font-size:24px;', '标题1:这是表格的主标题'), htmltools::h6(class = 'font-size:18px;', '标题2:这是表格的副标题') ) )
.top{caption-side: top; text-align:left;} .bottom{caption-side: bottom; text-align:left; line-height:90%;}
sketch1 = htmltools::withTags(table( caption(class = 'top', h4('主标题:这里写主标题'), h5('副标题:这里写副标题')), caption(class = 'bottom', h6('注1:数据来源'), h6('注2:其他说明')), thead(tr(th('客户范围'), th('有无'), th('留存人数'), th('流失人数'), th('等级'))))) datatable(data, container = sketch1, rownames = FALSE, options = list(dom = 'tp', pageLength = 3))
tbl <- datatable(data, options = list(dom = 'tp', pageLength = 3)) htmltools::div( htmltools::div( htmltools::h4("主标题:这是表格的副标题"), htmltools::h5("副标题:这是表格的副标题") ), tbl, htmltools::div(htmltools::h6("注1:数据来源"), htmltools::h6("注2:其他说明")) )
sketch2 = htmltools::withTags(table( thead(tr(class = 'firstHead', th(rowspan = 2, colspan = 1, '客户范围'), th(rowspan = 2, colspan = 1, '有无'), th(rowspan = 1, colspan = 2, '总客户数'), th(rowspan = 2, colspan = 1, '等级')), tr(class = 'secondHead', th(rowspan = 1, colspan = 1, '留存人数'), th(rowspan = 1, colspan = 1, '流失人数'))))) datatable( data, container = sketch2, options = list(dom = 'tp', pageLength = 3), rownames = FALSE, escape = FALSE)
datatable(data, options = list( pageLength = 5, columnDefs = list( # 引入自定义的 css 样式 list(targets = 1, class = 'dt-center ring'), list(targets = 2, class = 'dt-center className1'), list(targets = c(3, 4), class = 'className2'), # 如'dt-[head|body]-center'等官方定义的样式 # 可分别定义表头和表格主体的文本对齐方式 list(targets = 5, className = 'dt-head-right dt-body-left') )))
通过formatStyle()
函数设定的样式只对目标列的表格主体起作用。
list(targets = '_all', className = 'dt-head-center')
表示设置所有列的表格表头居中。
datatable(data, options = list(pageLength = 5, columnDefs = list( list(targets = '_all', className = 'dt-head-center')))) |> formatStyle( columns = 1, 'display' = 'flex', 'align-items' = 'center', 'justify-content' = 'center', 'margin' = 'auto', 'width' = '1.875rem', 'height' = '1.875rem', 'border' = '0.5px solid #555', 'border-radius' = '50%', 'color' = '#000', 'font-size' = '0.8125rem', 'letter-spacing' = '-1px') |> formatStyle( columns = 2, 'font-size' = '18px', 'color' = 'red', 'font-weight' = 'bold', 'text-align' = 'center', 'border-right' = '1px solid #555', 'background-color' = 'lightgrey') |> formatStyle( columns = c(3, 4), 'min-width' = '100px', 'text-align' = 'center') |> formatStyle(columns = 5, 'text-align' = 'center')
#为目标列'value1'准备填充渐变颜色所需的分段向量、颜色向量 brks <- quantile(data$value1, probs = seq(.05, .95, .05), na.rm = TRUE) clrs <- colorRampPalette(c("white", "red"))(length(brks) + 1) datatable(data, options = list(pageLength = 5, columnDefs = list( list(targets = '_all', className = 'dt-head-center')))) |> formatStyle( columns = 1, valueColumns = 'value1', 'background-color' = styleInterval(cuts = brks, values = clrs), 'display' = 'flex', 'margin' = 'auto', 'align-items' = 'center', 'justify-content' = 'center', 'width' = '1.875rem', 'height' = '1.875rem', 'border' = '0.5px solid rgb(0,0,0,0.1)', 'border-radius' = '50%', 'color' = '#000', 'font-size' = '0.8125rem', 'letter-spacing' = '-1px')|> formatStyle(columns = 2, 'color' = styleEqual(levels = c('YES', 'NO'), values = c('green', 'red'))) |> formatStyle(columns = 3, background = styleColorBar(data$value1, 'steelblue'), textAlign='right')
table().header()
和表格主体tables().body()
设置 css 样式。大括号里本来能够以逗号分隔的形式写入多个 css 样式,但是生成 isolides 幻灯片后有问题,所以只写了一个。datatable(data, options = list( initComplete = JS( "function(settings, json) { $(this.api().table().header()).css({ 'background-color': 'lightblue'}); $(this.api().tables().body()).css({ 'background-color': 'lightgrey'}); }") ))
column(3).header()
表示第三列的表头,column(3).nodes()
表示第三列的表格主体。datatable(data, options = list( pageLength = 5, initComplete = JS( "function(settings, json) { $(this.api().column(3).header()).css({ 'color': 'green','font-size':'24px'}); $(this.api().column(3).nodes()).css({ 'display': 'flex', 'align-items': 'center', 'justify-content': 'center', 'margin': 'auto', 'width': '1.875rem', 'height': '1.875rem', 'border': '1px solid #555', 'border-radius': '50%', 'color': '#000', 'font-size': '0.8125rem', 'letter-spacing': '-1px'}); }" ) ))
1.class/className
:先定义好 css 样式和样式名,通过class='样式名'
引入样式,一般情况下会对表格表头和表格主体同时起作用,仅对齐方式如className = 'dt-[head|body]-center'
可分别对表头或表格主体进行设置。
2.formatStyle()
:在formatStyle()
函数中直接写入需要设置的各样式属性和具体属性值,可对表格的列或行进行设置,可应用styleInterval()
等函数为不同行设置不同样式。
3.initComplete = JS()
:通过调用 DataTables API 对全表或单独一列的表头或表格主体设置样式。
4.如第一章改变图片样式时,单独对一列插入图片且设定了样式。同理,可对单独一列或多列如此设定样式。
datatable( data, options = list(columnDefs = list(list( targets = columns, render = JS("function(data, type, row, meta){ return '<div class=\"className\">' + data + '</div>' }"))
5.在设定表格标题、脚注或多行表头时,也可设置样式。