Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to color specific cells in a Data Frame / Table in R?

Tags:

css

r

formatting

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!

like image 382
gbrlrz017 Avatar asked Jul 09 '15 17:07

gbrlrz017


People also ask

How do I color cells in a table in R?

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.

How do I select specific rows and columns from a DataFrame in R?

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.

How do you refer to a specific column in a data frame in R?

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.


2 Answers

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"))) 

enter image description here

like image 74
lukeA Avatar answered Oct 19 '22 00:10

lukeA


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 have ncol(x) + 1 the first row will correspond to the rowname style. Correspondingly if the size is nrow(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)

enter image description here

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)))

enter image description here

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;')))

enter image description here

like image 32
rawr Avatar answered Oct 19 '22 00:10

rawr