在可反应的 r 包中使用分组行时如何呈现列总数(使用 javascript)?
How to render column total (with javascript) when using grouped rows in reactable r package?
我正在结合使用 crosstalk
和 reactable
。在 table 中,我使用分组行。现在我需要使用 javascript 添加一列总计。
---
title: "Focal Chart (Top)"
output:
flexdashboard::flex_dashboard:
orientation: rows
---
Inputs {.sidebar}
-------------------------------------
```{r}
library(crosstalk)
library(reactable)
cars <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]
data <- SharedData$new(cars)
filter_checkbox("type", "Type", data, ~Type)
filter_slider("price", "Price", data, ~Price, width = "100%")
filter_select("mfr", "Manufacturer", data, ~Manufacturer)
```
Row {data-height=500}
-------------------------------------
### Chart 1
```{r}
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(aggregated = JS("
function(cellInfo) {
// Calculate sum of all values in visible rows
var values = cellInfo.subRows.map(function(row) { return row.Price})
var total = values.reduce(function(a, b) { return a + b }, 0)
return total.toFixed(1)
}
"), footer = JS("function(colInfo) {
var values = colInfo.data.map(function(row) { return row[colInfo.column.id] })
var total = values.reduce(function(a, b) { return a + b }, 0)
return '$' + total.toFixed(2)
}")
),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)
```
Row {data-height=500}
-------------------------------------
### empty
```{r}
```
### empty
```{r}
```
如您所见,列总数为 $NaN。当然这是一个不希望的结果。如果我删除 groupBy
参数,列总计为 $471.80,这是应该的。有谁知道如何解决此 groupBy
行为?非常感谢!
我觉得这样就可以了,但是你搜一个厂家不刷新总数
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(footer = function(values) sprintf("$%.2f", sum(values))),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)
最初在 https://github.com/glin/reactable/issues/50 回答,只是复制到这里:
这是 Reactable 文档中的一个疏忽——自定义渲染文档没有提及当您拥有 grouped/nested 数据时 colInfo.data
的样子:https://glin.github.io/reactable/articles/custom-rendering.html#footers
通常,data
将是单个行数据对象的数组,例如
{
"Manufacturer": "Acura",
"Model": "Integra",
"Type": "Small",
"Price": 15.9
}
但是,当行被聚合时,单独的子行数据将嵌套在 _subRows
属性:
// For an aggregated row with 2 sub rows
{
"Manufacturer": "Acura",
"_subRows": [
{
"Manufacturer": "Acura",
"Model": "Integra",
"Type": "Small",
"Price": 15.9
},
{
"Manufacturer": "Acura",
"Model": "Legend",
"Type": "Midsize",
"Price": 33.9
}
]
}
您可以在 JS 函数中插入一个 console.log(colInfo)
以在浏览器的 JavaScript 控制台中探索完整的数据结构:
footer = JS("function(colInfo) {
console.log(colInfo)
}")
由于单个行数据现在是嵌套的,因此将所有内容总结起来需要做更多的工作,但这是使用两个 forEach
循环的一种方法:
library(reactable)
data <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(
aggregated = JS("function(cellInfo) {
// Calculate sum of all values in visible rows
var values = cellInfo.subRows.map(function(row) { return row.Price})
var total = values.reduce(function(a, b) { return a + b }, 0)
return total.toFixed(1)
}"),
footer = JS("function(colInfo) {
var total = 0
colInfo.data.forEach(function(row) {
row._subRows.forEach(function(data) {
total += data[colInfo.column.id]
})
})
return '$' + total.toFixed(2)
}")
),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)
我正在结合使用 crosstalk
和 reactable
。在 table 中,我使用分组行。现在我需要使用 javascript 添加一列总计。
---
title: "Focal Chart (Top)"
output:
flexdashboard::flex_dashboard:
orientation: rows
---
Inputs {.sidebar}
-------------------------------------
```{r}
library(crosstalk)
library(reactable)
cars <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]
data <- SharedData$new(cars)
filter_checkbox("type", "Type", data, ~Type)
filter_slider("price", "Price", data, ~Price, width = "100%")
filter_select("mfr", "Manufacturer", data, ~Manufacturer)
```
Row {data-height=500}
-------------------------------------
### Chart 1
```{r}
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(aggregated = JS("
function(cellInfo) {
// Calculate sum of all values in visible rows
var values = cellInfo.subRows.map(function(row) { return row.Price})
var total = values.reduce(function(a, b) { return a + b }, 0)
return total.toFixed(1)
}
"), footer = JS("function(colInfo) {
var values = colInfo.data.map(function(row) { return row[colInfo.column.id] })
var total = values.reduce(function(a, b) { return a + b }, 0)
return '$' + total.toFixed(2)
}")
),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)
```
Row {data-height=500}
-------------------------------------
### empty
```{r}
```
### empty
```{r}
```
如您所见,列总数为 $NaN。当然这是一个不希望的结果。如果我删除 groupBy
参数,列总计为 $471.80,这是应该的。有谁知道如何解决此 groupBy
行为?非常感谢!
我觉得这样就可以了,但是你搜一个厂家不刷新总数
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(footer = function(values) sprintf("$%.2f", sum(values))),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)
最初在 https://github.com/glin/reactable/issues/50 回答,只是复制到这里:
这是 Reactable 文档中的一个疏忽——自定义渲染文档没有提及当您拥有 grouped/nested 数据时 colInfo.data
的样子:https://glin.github.io/reactable/articles/custom-rendering.html#footers
通常,data
将是单个行数据对象的数组,例如
{
"Manufacturer": "Acura",
"Model": "Integra",
"Type": "Small",
"Price": 15.9
}
但是,当行被聚合时,单独的子行数据将嵌套在 _subRows
属性:
// For an aggregated row with 2 sub rows
{
"Manufacturer": "Acura",
"_subRows": [
{
"Manufacturer": "Acura",
"Model": "Integra",
"Type": "Small",
"Price": 15.9
},
{
"Manufacturer": "Acura",
"Model": "Legend",
"Type": "Midsize",
"Price": 33.9
}
]
}
您可以在 JS 函数中插入一个 console.log(colInfo)
以在浏览器的 JavaScript 控制台中探索完整的数据结构:
footer = JS("function(colInfo) {
console.log(colInfo)
}")
由于单个行数据现在是嵌套的,因此将所有内容总结起来需要做更多的工作,但这是使用两个 forEach
循环的一种方法:
library(reactable)
data <- MASS::Cars93[1:20, c("Manufacturer", "Model", "Type", "Price")]
reactable(
data,
groupBy = "Manufacturer",
searchable = TRUE,
columns = list(
Price = colDef(
aggregated = JS("function(cellInfo) {
// Calculate sum of all values in visible rows
var values = cellInfo.subRows.map(function(row) { return row.Price})
var total = values.reduce(function(a, b) { return a + b }, 0)
return total.toFixed(1)
}"),
footer = JS("function(colInfo) {
var total = 0
colInfo.data.forEach(function(row) {
row._subRows.forEach(function(data) {
total += data[colInfo.column.id]
})
})
return '$' + total.toFixed(2)
}")
),
Manufacturer = colDef(footer = "Total")
),
defaultColDef = colDef(footerStyle = list(fontWeight = "bold"))
)