R - Conditional row highlighting in HTML table created using xtable or kable

9.9k views Asked by At

I'm pretty much a beginner at programmatically formatting R output, but I've got a basic understanding of knitr, xtable, Markdown, and Pandoc's ability to convert one markup format to another. What I want to do is write an R dataframe df to an HTML table, and apply a particular color to each row that meets a condition (e.g., df$outcome == 1). However, I'm not sure which package would accomplish this in a simple and efficient way, but from browsing a few table formatting threads (xtable thread 1, xtable thread 2, kable documentation 1), I've gathered that kable and xtable might be capable of accomplishing my desired result.

To clarify, here is my reproducible example (using xtable, but am interested in an answer using kable or another package as well):

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

library(xtable)
dfxt <- xtable(df)

knit2html(input      = "~/rowcolor_ex.Rmd",
          output     = OUTPUTHERE
          stylesheet = "STYLESHEET.css")

withknit2html referencing the file named "rowcolor_ex.Rmd", shown below:

```{r,echo=FALSE,results='asis',warning=FALSE,message=FALSE}
print(dfxt, 
      type = "html",
      include.rownames = FALSE,)
```

I understand that if I'm to use xtable, I'd include one or more arguments after the print(dfxt, part of the function call in the Rmd document, and this thread shows the add.to.row argument that makes sense for type = "latex", but it isn't clear how the code would change for HTML output. Also, I'm not sure if referencing a CSS stylesheet in knit2html would override the HTML table's formatting.

4

There are 4 answers

8
rawr On BEST ANSWER

Here is a solution using Gmisc::htmlTable

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(Gmisc)
htmlTable(as.matrix(df), altcol = cols, 
          rgroup = '', n.rgroup = rep(1, length(cols)))

EDIT

Since htmlTable has since been moved to the package, htmlTable, and is no longer in Gmisc >= 1.0, the new way to do this would be

library('htmlTable')
htmlTable(as.matrix(df), col.rgroup = cols)

which also gives:

enter image description here

and your markdown code would simply be

```{r, results='asis'}
htmlTable(as.matrix(df), altcol = cols, 
          rgroup = '', n.rgroup = rep(1, length(cols)))
```

And my .Rmd would look like:

---
output: 
  html_document:
    css: ~/knitr.css
---

```{r, results='asis', message=FALSE}
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(Gmisc)
htmlTable(as.matrix(df), altcol = cols, 
          rgroup = '', n.rgroup = rep(1, length(cols)))
```
0
daroczig On

Well, not using colors (as not supported by markdown), but you can highlight cells/rows/columns of the table with pandoc.table and the general pander method by using bold or italics font face:

> library(pander)
> emphasize.rows(which(df$outcome == 2))
> pander(df)

-------------------------
 id   inputval   outcome 
---- ---------- ---------
 29     0.89        1    

*79*   *0.69*      *2*   

*41*   *0.64*      *2*   

*89*    *1*        *2*   

 95     0.66        1    

 5      0.71        1    

 53     0.54        1    

*90*   *0.6*       *2*   

*56*   *0.29*      *2*   

 46     0.14        4    

 96     0.97        1    

*46*   *0.91*      *2*   

 68     0.69        4    

 58     0.8         1    

 11     0.02        3    

 90     0.48        1    

 25     0.76        1    

 5      0.21        4    

 33     0.32        4    

*96*   *0.23*      *2*   
-------------------------
0
David Gohel On

Here is a solution using ReporteRs:

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

library( ReporteRs )
library( magrittr )

# create and format table
myft = df %>% FlexTable() %>% 
  setRowsColors( df$outcome == 1, 'magenta') %>% 
  setFlexTableWidths( c( 1, 1, 1) )

# create an html doc and send myft into
doc = bsdoc() %>% addFlexTable( myft )

# write the html file in a new dir
writeDoc( doc, "example_out/df.html")
0
Devuroasts On

I've played around a good amount with formatting RMarkdown documents.

Since RMarkdown gets converted to LaTeX before the end PDF is generated, you can pass arguments that would work in LaTeX to RMarkdown. So, adding

header-includes:
  - \usepackage{xcolor}

in the heading of the RMarkdown document, and then adding something like

for(i in seq(1, nrow(yourDataframe), by = 2)){
  yourDataframe[i, ] <- paste0("\\color{purple}", yourDataframe[i, ])
  row.names(yourDataframe)[i] <- paste0("\\color{purple}", row.names(yourDataframe)[i])
}

will get you purple (or whatever color specified and allowed in the xcolor LaTeX package) entries in every other row of your table. Just another way to emphasize entries that isn't the base bold or italics given.

This isn't row highlighting, but could give you further customizable options.

*Tested with the pander package.

**You'll need to convert any factor columns to character columns for this method.

Output