我的结论是你不能使用
DT
将两个格式化器添加到同一列中,尽管当然我可能错了。
请注意,即使在
DT
的文档中没有明确说明,每列表格只能添加一个格式化器。还要注意,在您提供的链接示例或输入
?formatCurrency
时,当它们包含两个管道符号
%>%
时,它们总是影响两个不同的列。
在您的示例中,当您执行以下操作时:
datatable(m) %>% formatRound("A", digits=1) %>% formatCurrency("A", currency="£")
结果将保留一位小数且不带货币符号,如下所示:
datatable(m) %>% formatCurrency("A", currency="£") %>% formatRound("A", digits=1)
结果是货币加上没有舍入的数字。
我对R如何与js集成的了解非常有限,但是看着
cran软件包中的R源代码,似乎每个管道中的格式命令都会追加一个格式化程序,但由于某种原因只有一个格式化程序起作用:
formatCurrency = function(table, columns, currency = '$', interval = 3, mark = ',') {
formatColumns(table, columns, tplCurrency, currency, interval, mark)
}
formatRound = function(table, columns, digits = 2) {
formatColumns(table, columns, tplRound, digits)
}
formatColumns = function(table, columns, template, ...) {
...
x$options$rowCallback = appendFormatter(
x$options$rowCallback, columns, colnames, rownames, template, ...
)
...
}
appendFormatter = function(js, name, names, rownames = TRUE, template, ...) {
...
JS(append(
js, after = 1,
template(i, ...)
))
}
每个格式化程序最终都会调用
formatColumns
,并使用不同的
template
,而
i
会解析列的id。正如我所说,我不知道这是因为追加操作覆盖了格式化程序,还是与执行有关。
< p > < em >编辑:抱歉我不小心按下了发布按钮并被打断了。实际上,我实现了一个接受更多参数的格式化程序。解决方案有点复杂,但它可以工作。这是一个接受货币和数字的格式化程序:
tplRound2 = function(cols, currency, digits) {
sprintf(
"var d = parseFloat(data[%d]); $(this.api().cell(row, %s).node()).html(isNaN(d) ? '' : '%s' + d.toFixed(%d).toString());",
cols, cols, currency, digits
)
}
你需要将所有这些函数添加到你的会话中:
formatRound2 = function(table, columns, currency, digits = 2) {
formatColumns2(table, columns, tplRound2, currency, digits)
}
formatColumns2 = function(table, columns, template, ...) {
if (inherits(columns, 'formula')) columns = all.vars(columns)
x = table$x
colnames = base::attr(x, 'colnames', exact = TRUE)
rownames = base::attr(x, 'rownames', exact = TRUE)
x$options$rowCallback = appendFormatter2(
x$options$rowCallback, columns, colnames, rownames, template, ...
)
table$x = x
table
}
name2int = function(name, names) {
if (is.numeric(name)) {
return(if (all(name > 0)) name else seq_along(names)[name])
}
names = setNames(seq_along(names), names)
unname(names[name])
}
appendFormatter2 = function(js, name, names, rownames = TRUE, template, ...) {
js = if (length(js) == 0) c('function(row, data) {', '}') else {
unlist(strsplit(as.character(js), '\n'))
}
i = name2int(name, names)
if (is.character(name) || (is.numeric(name) && !rownames)) i = i - 1
if (any(is.na(i))) stop(
'You specified the columns: ', paste(name, collapse = ', '), ', ',
'but the column names of the data are ', paste(names, collapse = ', ')
)
JS(append(
js, after = 1,
template(i, ...)
))
}
然后您可以使用新的格式化程序运行,以获得所需的结果:
datatable(m) %>% formatRound2("A", "£", digits=1)
(但是这不会在每三个数字后添加
,
,如果您真的需要,我可以将其添加到格式化程序中...)
评论后的EDIT2:
这将是同时使用货币和数字位数以及','标记的格式化函数:
tplRound3 = function(cols, currency, digits, interval, mark) {
sprintf(
"var d = parseFloat(data[%d]); $(this.api().cell(row, %s).node()).html(isNaN(d) ? '' : '%s' + d.toFixed(%d).toString().replace(/\\B(?=(\\d{%d})+(?!\\d))/g, '%s'));",
cols, cols, currency, digits, interval, mark
)
}
formatRound3 = function(table, columns, currency, digits = 2, interval=3, mark=',') {
formatColumns2(table, columns, tplRound3, currency, digits, interval, mark)
}
为了使用它,只需输入
datatable(m) %>% formatRound3("A", "£", digits=1)