1

我正在crosstalkreactable. 在表中,我使用分组行。现在我需要使用 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行为?提前谢谢了!

4

2 回答 2

1

我认为这种方法可以满足您的需求,但是如果您搜索一个制造商,它不会刷新总数。

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"))
)
于 2020-06-15T18:31:35.530 回答
1

最初在https://github.com/glin/reactable/issues/50回答,在这里复制它:

这是可反应文档中的一个疏忽——自定义渲染文档没有提到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 函数中插入 aconsole.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"))
)
于 2020-06-17T06:08:18.950 回答