Search code examples
rdtformattable

How to customize datatable by row with custom threshold


This is related to this other question link.

Currently I'm using this code in order to apply some styling to my table.

I need to color each cell only if the value exceeds the 3rd quantile of the row, the problem is that DT doesn't seem to allow to work by row, just by column.

formattable() works ok, but I lose some useful proprieties from DT, for example the possibility to edit the cell with editable=T.

library(formattable)
library(DT)

dat <- as.data.frame(matrix(AirPassengers, ncol=12, byrow=T))

find_anomaly <- function(x) {
  q3 <- quantile(x, 0.75)
  q3
}

ftable <- formattable(dat, lapply(1:nrow(dat), function(row) {
  area(row, col = 1:12) ~ formatter("span", style = x ~ ifelse(x > find_anomaly(x),
                                                               style(
                                                                 display = "block",
                                                                 padding = "0 4px",
                                                                 "border-radius" = "4px",
                                                                 "color" = csscolor("white"),
                                                                 "background-color" = csscolor(
                                                                   gradient(as.numeric(x),"white", "orangered"))),
                                                               NA))
}))

as.datatable(ftable, editable=T)

Here you can see that all is good except that the table shows the HTML from formattable() once clicked:

enter image description here

Is there a way to keep the styling generated from formattable that works ok with editable=T?


Solution

  • Here is a solution with DT, applying the render option to each column:

    library(DT)
    
    products <- data.frame(
      X1 = round(runif(5),2),
      X2 = round(runif(5),2),
      X3 = round(runif(5),2),
      X4 = round(runif(5),2),
      X5 = round(runif(5),2),
      X6 = round(runif(5),2),
      X7 = round(runif(5),2),
      X8 = round(runif(5),2),
      X9 = round(runif(5),2),
      X10 = round(runif(5),2)
    )
    
    render <- c(
      "function(data, type, row){",
      "  if(type === 'display'){",
      "    var arr = row.slice();",
      "    arr.sort();",
      "    var per75 =  Math.floor(row.length*.75) - 1;",
      "    var s = data >= arr[per75] ? '<span style=\"padding: 0 4px; border-radius: 4px; background-color: red;\">' + data + '</span>' : data;",
      "    return s;",
      "  } else {",
      "    return data;",
      "  }",
      "}"
    )
    
    datatable(products, editable = "cell", rownames = FALSE, 
              options = list(
                columnDefs = list(
                  list(targets = "_all", render = JS(render))
                )
              )
    )
    

    enter image description here