闪亮的数据表页脚回调总和
shiny DataTables footer Callback sums
我正在为 DataTables
在一个类似于 this example from the DataTables
forum. My thought so far from reading the DT
documentation 的应用程序中为 DataTables
实现一个 callback
函数(第 4.4 节),它可能会通过 options
的 columnDefs
参数应用相同的 class sum
,如下所示,但如果我只知道将 JS 参数放在哪里来执行 classes 像 link 中那样手动。
您可以删除所有 columnDefs
和 callback
参数以查看示例起点。
app.R
library(shiny)
library(DT)
ui <- fluidPage(
title = 'Select Table Rows',
hr(),
h1('A Server-side Table'),
fluidRow(
column(9, DT::dataTableOutput('x3'))
)
)
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
fixedHeader = TRUE,
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
# columnDefs = JS("[
# { className: 'sum', 'targets': [ 1,2 ] }
# ]")
# ),
#callback = JS(
# " function(row, data, start, end, display) {
# var api = this.api();
#
# api.columns('.sum', { page: 'current' }).every(function () {
# var sum = api
# .cells( null, this.index(), { page: 'current'} )
# .render('display')
# .reduce(function (a, b) {
# var x = parseFloat(a) || 0;
# var y = parseFloat(b) || 0;
# return x + y;
# }, 0);
# console.log(this.index() +' '+ sum); //alert(sum);
# $(this.footer()).html(sum);
# });
#}"
)
)
)
}
shinyApp(ui = ui, server = server)
最终解决方案:
library(shiny)
library(DT)
ui <- fluidPage(
title = 'Select Table Rows',
hr(),
h1('A Server-side Table'),
fluidRow(
column(9, DT::dataTableOutput('x3'))
)
)
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
sketch <- htmltools::withTags(table(
class = "display",
style = "bootstrap",
tableHeader(colnames(mtcars2)),
tableFooter(colnames(mtcars2))
))
output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
container = sketch,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
footerCallback = JS(
"function( tfoot, data, start, end, display ) {",
"var api = this.api(), data;",
"total = api.column( 1, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total1 = api.column( 2, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total2 = api.column( 3, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total3 = api.column( 4, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total4 = api.column( 5, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total5 = api.column( 6, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total6 = api.column( 7, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total7 = api.column( 8, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"$( api.column( 1 ).footer() ).html(total.toFixed(2));
$( api.column( 2 ).footer() ).html(total1.toFixed(2));
$( api.column( 3 ).footer() ).html(total2.toFixed(2));
$( api.column( 4 ).footer() ).html(total3.toFixed(2));
$( api.column( 5 ).footer() ).html(total4.toFixed(2));
$( api.column( 6 ).footer() ).html(total5.toFixed(2));
$( api.column( 7 ).footer() ).html(total6.toFixed(2));
$( api.column( 8 ).footer() ).html(total7.toFixed(2));",
"}"
))
))
}
shinyApp(ui = ui, server = server)
我意识到这对 JS 来说可能是错误的形式,但是,在我的情况下,这最有效,因此我可以对每个选项应用不同的选项(一些货币符号、一些平均值、不同的小数精度等)。
为了在页脚中显示 sum/total,您必须向 table 添加一个容器,如下所示。我还更改了 JS 代码:下面提供的版本必须有效。不幸的是,我无法判断您的 JS 代码有什么问题,因为我不是 javascript 人。您可以使用 HTML(...) 部分来更改总和的显示方式。
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
sketch = htmltools::withTags(table(tableFooter(c("",0,0,0,0,0,0,0,0))))
output$x3 = DT::renderDataTable(DT::datatable(mtcars2, container = sketch,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
fixedHeader = TRUE,
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
footerCallback = JS(
"function( tfoot, data, start, end, display ) {",
"var api = this.api();",
"$( api.column( 1 ).footer() ).html(",
"api.column( 1).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 2 ).footer() ).html(",
"api.column( 2 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 3 ).footer() ).html(",
"api.column( 3 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 4 ).footer() ).html(",
"api.column( 4 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 5 ).footer() ).html(",
"api.column( 5 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 6 ).footer() ).html(",
"api.column( 6 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 7 ).footer() ).html(",
"api.column( 7 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 8 ).footer() ).html(",
"api.column( 8 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"}")
)
)
)
}
我精心设计了此函数作为有关总计和格式的可能解决方案。如果您需要 运行 一个复杂的操作,只需 运行 之前的代码,然后插入值作为 operation = "custom"
。希望对你有帮助。
library(DT)
dat <- iris[1:4]
sketch <- htmltools::tags$table(
tableHeader(names(dat)),
tableFooter(rep("", ncol(dat))))
js_op <- function(column, operation, name = "", signif = 3) {
# Auxiliar function for mean
aux <- ifelse(
operation == "mean",
paste0("map(function(num) { return num/data.length; })."), "")
# Decimals to consider
signif <- 10^signif
# Operation
if (operation %in% c("sum", "mean"))
operation <- paste0("Math.round((a+b)*",signif,")/",signif)
if (operation == "count")
operation <- "data.length"
if (operation == "custom")
return(paste0("$(api.column(", column, ").footer()).html('", name, "')"))
# Result
res <- paste0(
"$(api.column(", column, ").footer()).html('", name, "'+",
"api.column(", column, ").data().", aux, "reduce( function ( a, b ) {",
"return ", operation, ";",
"} ));")
return(res)
}
javascript <- JS(
"function(tfoot, data, start, end, display ) {",
"var api = this.api(), data;",
js_op(0, operation = "count", name = "Counter: "),
js_op(1, operation = "sum", name = "Sum: "),
js_op(2, operation = "mean", name = "Mean: "),
js_op(3, operation = "custom", name = "Something"),
";}")
datatable(iris[,1:4], rownames = FALSE, container = sketch,
options = list(footerCallback = javascript))
我正在为 DataTables
在一个类似于 this example from the DataTables
forum. My thought so far from reading the DT
documentation 的应用程序中为 DataTables
实现一个 callback
函数(第 4.4 节),它可能会通过 options
的 columnDefs
参数应用相同的 class sum
,如下所示,但如果我只知道将 JS 参数放在哪里来执行 classes 像 link 中那样手动。
您可以删除所有 columnDefs
和 callback
参数以查看示例起点。
app.R
library(shiny)
library(DT)
ui <- fluidPage(
title = 'Select Table Rows',
hr(),
h1('A Server-side Table'),
fluidRow(
column(9, DT::dataTableOutput('x3'))
)
)
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
fixedHeader = TRUE,
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
# columnDefs = JS("[
# { className: 'sum', 'targets': [ 1,2 ] }
# ]")
# ),
#callback = JS(
# " function(row, data, start, end, display) {
# var api = this.api();
#
# api.columns('.sum', { page: 'current' }).every(function () {
# var sum = api
# .cells( null, this.index(), { page: 'current'} )
# .render('display')
# .reduce(function (a, b) {
# var x = parseFloat(a) || 0;
# var y = parseFloat(b) || 0;
# return x + y;
# }, 0);
# console.log(this.index() +' '+ sum); //alert(sum);
# $(this.footer()).html(sum);
# });
#}"
)
)
)
}
shinyApp(ui = ui, server = server)
最终解决方案:
library(shiny)
library(DT)
ui <- fluidPage(
title = 'Select Table Rows',
hr(),
h1('A Server-side Table'),
fluidRow(
column(9, DT::dataTableOutput('x3'))
)
)
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
sketch <- htmltools::withTags(table(
class = "display",
style = "bootstrap",
tableHeader(colnames(mtcars2)),
tableFooter(colnames(mtcars2))
))
output$x3 = DT::renderDataTable(DT::datatable(mtcars2,
container = sketch,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
footerCallback = JS(
"function( tfoot, data, start, end, display ) {",
"var api = this.api(), data;",
"total = api.column( 1, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total1 = api.column( 2, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total2 = api.column( 3, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total3 = api.column( 4, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total4 = api.column( 5, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total5 = api.column( 6, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total6 = api.column( 7, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"total7 = api.column( 8, { page: 'current'} ).data().reduce( function ( a, b ) {return a + b;} )",
"$( api.column( 1 ).footer() ).html(total.toFixed(2));
$( api.column( 2 ).footer() ).html(total1.toFixed(2));
$( api.column( 3 ).footer() ).html(total2.toFixed(2));
$( api.column( 4 ).footer() ).html(total3.toFixed(2));
$( api.column( 5 ).footer() ).html(total4.toFixed(2));
$( api.column( 6 ).footer() ).html(total5.toFixed(2));
$( api.column( 7 ).footer() ).html(total6.toFixed(2));
$( api.column( 8 ).footer() ).html(total7.toFixed(2));",
"}"
))
))
}
shinyApp(ui = ui, server = server)
我意识到这对 JS 来说可能是错误的形式,但是,在我的情况下,这最有效,因此我可以对每个选项应用不同的选项(一些货币符号、一些平均值、不同的小数精度等)。
为了在页脚中显示 sum/total,您必须向 table 添加一个容器,如下所示。我还更改了 JS 代码:下面提供的版本必须有效。不幸的是,我无法判断您的 JS 代码有什么问题,因为我不是 javascript 人。您可以使用 HTML(...) 部分来更改总和的显示方式。
server <- function(input, output, session) {
# server-side processing
mtcars2 = mtcars[, 1:8]
sketch = htmltools::withTags(table(tableFooter(c("",0,0,0,0,0,0,0,0))))
output$x3 = DT::renderDataTable(DT::datatable(mtcars2, container = sketch,
extensions = 'Buttons',
options = list(
scrollX = TRUE,
scrollY = TRUE,
pageLength = 10,
order = list(list(1, 'asc')),
fixedHeader = TRUE,
dom = 'Blrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')
footerCallback = JS(
"function( tfoot, data, start, end, display ) {",
"var api = this.api();",
"$( api.column( 1 ).footer() ).html(",
"api.column( 1).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 2 ).footer() ).html(",
"api.column( 2 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 3 ).footer() ).html(",
"api.column( 3 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 4 ).footer() ).html(",
"api.column( 4 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 5 ).footer() ).html(",
"api.column( 5 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 6 ).footer() ).html(",
"api.column( 6 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 7 ).footer() ).html(",
"api.column( 7 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"$( api.column( 8 ).footer() ).html(",
"api.column( 8 ).data().reduce( function ( a, b ) {",
"return a + b;",
"} )",
");",
"}")
)
)
)
}
我精心设计了此函数作为有关总计和格式的可能解决方案。如果您需要 运行 一个复杂的操作,只需 运行 之前的代码,然后插入值作为 operation = "custom"
。希望对你有帮助。
library(DT)
dat <- iris[1:4]
sketch <- htmltools::tags$table(
tableHeader(names(dat)),
tableFooter(rep("", ncol(dat))))
js_op <- function(column, operation, name = "", signif = 3) {
# Auxiliar function for mean
aux <- ifelse(
operation == "mean",
paste0("map(function(num) { return num/data.length; })."), "")
# Decimals to consider
signif <- 10^signif
# Operation
if (operation %in% c("sum", "mean"))
operation <- paste0("Math.round((a+b)*",signif,")/",signif)
if (operation == "count")
operation <- "data.length"
if (operation == "custom")
return(paste0("$(api.column(", column, ").footer()).html('", name, "')"))
# Result
res <- paste0(
"$(api.column(", column, ").footer()).html('", name, "'+",
"api.column(", column, ").data().", aux, "reduce( function ( a, b ) {",
"return ", operation, ";",
"} ));")
return(res)
}
javascript <- JS(
"function(tfoot, data, start, end, display ) {",
"var api = this.api(), data;",
js_op(0, operation = "count", name = "Counter: "),
js_op(1, operation = "sum", name = "Sum: "),
js_op(2, operation = "mean", name = "Mean: "),
js_op(3, operation = "custom", name = "Something"),
";}")
datatable(iris[,1:4], rownames = FALSE, container = sketch,
options = list(footerCallback = javascript))