Search code examples
cssrdataframehtml-tablekableextra

How to create dynamic HTML table in R


I am using the following structured dataframe in R.

Dataframe<-

seq      count  percentage   Marking     count     Percentage     batch_no   count    Percentage
FRD      1      12.50%       S1          2         25.00%         6          1        12.50%
FHL      1      12.50%       S2          1         12.50%         7          2        25.00%
ABC      2      25.00%       S3          1         12.50%         8          2        25.00%
DEF      1      12.50%       Hold        2         25.00%         9          1        12.50%
XYZ      1      12.50%       NA          1         12.50%         NA         1        12.50%
ZZZ      1      12.50%       (Blank)     1         12.50%         (Blank)    1        12.50%
FRD      1      12.50%         -         -           -             -         -           -
NA       1      12.50%         -         -           -             -         -           -
(Blank)  0      0.00%          -         -           -             -         -           -
Total    8      112.50%        -         8         100.00%         -         8         100.00%

The dataframe have number of columns static but number of rows can be vary from. For Example with some condition number of rows might be 15 or less may be 4 or 5.

I need to add table header color as light green with bold font and last row of the table as yellow with bold font. Also, Need to add the condition that if Percentage of Hold in marking and Percentage of 8 in batch_no is >25% mark it as a dark red with bold white font.

If possible, can we add the suffix in S3 as S3 (In Progress) and 9 as `9 (In Progress) where the font of (In Progress) will be 2 font less than variable name.

The added text (In Progress) should be in yellow font with bold.

I'm Using the below mentioned code:

library(tableHTML)
library(dplyr)

add_font <- function(x) {
  x <- gsub('\\(', '\\(<font size="-1">', x)
  x <- gsub('\\)', '</font>\\)', x)
  return(prettyNum(x, big.mark = ','))
}


    Html_Table<-Dataframe %>% 
      mutate(`Marking` = add_font(`Marking`),
             `batch_no` = add_font(`batch_no`)) %>% 
      tableHTML(rownames = FALSE, 
                escape = FALSE,
                widths = rep(100, 12),
                caption = "Dataframe: Test",
                theme='scientific') %>% 
      add_css_caption(css = list(c("font-weight", "border","font-size"),
                                 c("bold", "1px solid black","16px"))) %>%
      add_css_row(css = list(c("background-color"), c("lightblue")), rows = 0:1)%>%
      add_css_caption(css = list(c("background-color"), c("lightblue"))) %>%
      add_css_row(css = list('background-color', '#f2f2f2'),
                  rows = odd(1:10)) %>%
      add_css_row(css = list('background-color', '#e6f0ff'),
                  rows = even(1:10)) %>%
      add_css_row(css = list(c("background-color","font-weight"), c("yellow", "bold")), 
                   rows = even(2:3)) %>%
      add_css_row(css = list(c("font-style","font-size"), c("italic","12px")), 
                   rows = 4:8)

Solution

  • You can actually use exactly what you did with add_font to get what you need with tableHTML

    library(tableHTML)
    library(dplyr)
    Dataframe <- read.table(text='seq      count  percentage   Marking     count     percentage     batch_no   count    percentage
    FRD      1      12.50%       S1          2         25.00%         6          1        12.50%
    FHL      1      12.50%       S2          1         12.50%         7          2        25.00%
    ABC      2      25.00%       S3          1         12.50%         8          2        25.00%
    DEF      1      12.50%       Hold        2         25.00%         9          1        12.50%
    XYZ      1      12.50%       NA          1         12.50%         NA         1        12.50%
    ZZZ      1      12.50%       (Blank)     1         12.50%         (Blank)    1        12.50%
    FRD      1      12.50%         -         -           -             -         -           -
    NA       1      12.50%         -         -           -             -         -           -
    (Blank)  0      0.00%          -         -           -             -         -           -
    Total    8      112.50%        -         8         100.00%         -         8         100.00%',
                            header = TRUE, stringsAsFactors = FALSE) %>% as_tibble()
    names_orig <- Dataframe %>% names()
    
    # add numeric columns to get the conditions
    Dataframe$percentage.1_num <- gsub("%", "", Dataframe$percentage) %>% as.numeric()
    Dataframe$percentage.2_num <- gsub("%", "", Dataframe$percentage.1) %>% as.numeric()
    
    add_font <- function(x) {
      x <- gsub('\\(', '\\(<font size="-1">', x)
      x <- gsub('\\)', '</font>\\)', x)
      return(x)
    }
    
    add_style <- function(x, style){
      x <- paste0('<div ', style, '>', x, '</div>')
      return(x)
    }
    
    add_in_progress <- function(x){
      x <- paste0(x, '<font size="1" color="red">', '(In Progress)', '</font>')
      return(x)
    }
    
    # define the style you want to apply where the condition hold
    style <- 'style="background-color:darkred;font-weight:bold;color:white;"'
    
    condition_1 <- Dataframe$Marking=='Hold' & Dataframe$percentage.1_num > 10
    condition_2 <- Dataframe$batch_no==8 & Dataframe$percentage.2_num > 10
    
    
    Html_Table<-
      Dataframe  %>%
      mutate(`Marking` = add_font(`Marking`),
             `batch_no` = add_font(`batch_no`)) %>% 
      # add the style where the condition holds
      mutate(percentage = ifelse(condition_1,
                                 add_style(percentage, style),
                                 percentage),
             # Marking = ifelse(condition_1,
             #                  add_style(Marking, style),
             #                  Marking),
             percentage.1 = ifelse(condition_2,
                                   add_style(percentage.1, style),
                                   percentage.1),
             # batch_no = ifelse(condition_2,
             #                   add_style(batch_no, style),
             #                   batch_no)
             ) %>%
      # add in progress where the condition holds
      mutate(Marking = ifelse(Marking=='S3', 
                              add_in_progress(Marking), 
                              Marking))  %>%
      mutate(batch_no = ifelse(batch_no=='9', 
                               add_in_progress(batch_no), 
                               batch_no)) %>% 
      # select the columns you want to show
      select(names_orig) %>%  
      # give it to tableHTML, you could also set the headers you want to show
      # and replace character NA with the empty string
      tableHTML(rownames = FALSE, 
                escape = FALSE,
                widths = rep(100, 9),
                replace_NA = '',
                headers = names_orig %>% gsub('.[1-9]', '', .),
                caption = "Dataframe: Test", 
                border = 0) %>%
      # header style
      add_css_header(css = list(c('background-color', 'border-top', 'border-bottom'), 
                                c('lightgreen', '3px solid black', '3px solid black')), 
                     headers = 1:ncol(Dataframe)) %>% 
      # last row style
      add_css_row(css = list(c('background-color', 'font-weight'), 
                             c('yellow', 'bold')), 
                  rows = nrow(Dataframe)+1)
    
    Html_Table
    

    enter image description here