I would like to color specific cells in the following dataframe. For example, in the inputval column, I would like to highlight cells in the range of [0.8, 0.9)
magenta, and the cells in that same column in the range of [0.7, 0.8)
blue. Similarly, I'd like the output column cells with a value of 1 to be colored magenta and those with value 4 to be colored blue. For the rest of the cells in the dataframe, I would like them to remain white.
I have the following reproducible code which highlights by row only, and limits me to coloring in magenta and white only. How can I add another color and do so by cell?
set.seed(123)
df <- data.frame(id = sample(1:100, 20, replace = TRUE),
inputval = sample(seq(0, 1, by=0.01), 20, replace = TRUE),
outcome = sample(1:4, 20, replace = TRUE))
cols <- with(df, ifelse(outcome == 1, 'magenta', 'white'))
library('htmlTable')
htmlTable(as.matrix(df), col.rgroup = cols)
I realize that the issue for adding different colors is with the ifelse
call in with
that limits me to just magenta and white. How can I add another condition here?
While I know what's causing the multiple color issue, I'm pretty clueless about how to color only specific cells.
This is the same example as the accepted answer to this question. Thanks!
It's possible to add color to data cells according to their values. The data_color() function colors all rows of any columns supplied. There are two ways to define how cells are colored: (1) through the use of a supplied color palette, and (2) through use of a color mapping function available from the scales package.
By using bracket notation on R DataFrame (data.name) we can select rows by column value, by index, by name, by condition e.t.c. You can also use the R base function subset() to get the same results. Besides these, R also provides another function dplyr::filter() to get the rows from the DataFrame.
Data in data frames can be addressed by index (subsetting), by logical vector, or by name (columns only). Use the $ operator to address a column by name.
Have you considered DT
?
library(DT)
datatable(df, rownames = FALSE) %>%
formatStyle(columns = "inputval",
background = styleInterval(c(0.7, 0.8, 0.9)-1e-6, c("white", "lightblue", "magenta", "white"))) %>%
formatStyle(columns = "outcome",
background = styleEqual(c(1, 4), c("magenta", "lightblue")))
My answer below is really dumb.. Here is the proper way:
This feature is built into htmlTable
via the css.cell
argument:
The
css.cell
element allows you to add any possible CSS style to your table cells. If you provide a vector the vector it is assummed that the styles should be repeated throughout the columns. If you provide a matrix of the same size as your x argument. If havencol(x) + 1
the first row will correspond to the rowname style. Correspondingly if the size isnrow(x) + 1
it is assummed that the first row is the header row.
So Basically you just need to define a matrix of styles for each cell:
x <- head(cars)
## indices defining where the styles go
where <- rbind(c(2,2), c(2,1), c(5,2))
style <- c('background-color: red; color: white;',
'border: solid 1px;',
'font-weight: 900; color: blue;')
css.cell <- matrix('', nrow(x), ncol(x))
css.cell[where] <- style
# [,1] [,2]
# [1,] "" ""
# [2,] "border: solid 1px;" "background-color: red; color: white;"
# [3,] "" ""
# [4,] "" ""
# [5,] "" "font-weight: 900; color: blue;"
# [6,] "" ""
htmlTable(head(cars), css.cell = css.cell)
It's hard to tell unless you are swapping back and forth, but the spacing in this table and the similar one below is slightly different. The inject_div
example looks a little more centered.
A little late, but @CyrusMohammadian made a comment on my other answer, and since the comment/question is the same as this one, I'll add the answer here rather than editing my answer which was for a (slightly) different question.
Tables can get complex, and everyone has different features they want. I don't think it is possible for Max to have solutions built-in for them all.
Therefore, the easiest way I think would be to (hackily) inject some html/css into your table (you could probably also do this after running htmlTable
, ie directly in the html code, but this is easier I think):
#' Inject div
#'
#' Inject an html division tag with style attribute.
#'
#' @param x a matrix or data frame
#' @param where an \code{nx2} matrix of row and column indices or vector (of
#' the form c(row, col, row, col, ...)) specifying which cells to select
#' @param style vector of character string(s) applied to each cell, recycled
#' if necessary
inject_div <- function(x, where, style = 'background-color: lightgrey; border: solid 1px') {
if (!all(sapply(style, nzchar)))
return(x)
where <- matrix(where, ncol = 2L, byrow = !is.matrix(where))
style <- rep_len(style, nrow(where))
if (length(where) > 0)
x[where] <- sprintf('<div style=\'%s\'>%s</div>',
gsub(';*$', ';', style), x[where])
x
}
library('htmlTable')
htmlTable(inject_div(head(cars), cbind(2,2)))
htmlTable(inject_div(head(cars), where = c(2,2,2,1,5,2),
## equivalently
# where = rbind(c(2,2), c(2,1), c(5,2))
style = c('background-color: red; color: white;',
'border: solid 1px;',
'font-weight: 900; color: blue;')))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With