Figures referenced below I am new to R and RStudio, and landed on using the tableHTML package because it seems like a good fit to format my dataframe. I have a dataframe (tibia_outliers_shortable) listing only the low and high outlier values for each of several variables across many subjects, cropped here to one variable across 9 subjects. I want to change the cell background-color of cells with values below the "low outlier cutoff" to light blue, and the background-color of cells with values above the "high outlier cutoff" to red.
When I use add_css_conditional_column() to change the background for cells with high values, it misses the cell with the highest values - see Fig 1.
If I then run the same tableHTML() command but add another call to add_css_conditional_column() to highlight cells with low values, it formats the empty cells (maybe treats them as zeroes?) and also formats the highest value cell! See Fig 2.
patients <- c('PatNo 869','PatNo 885','PatNo 888','PatNo 1005','PatNo 1007','PatNo 1016','PatNo 1028','PatNo 1043','PatNo 1044')
vals = rbind("",427.3,978.3,"",423.2,967.4,"",1042.9,"")
tibia_outliers_shorter <- data.frame(vals,row.names = patients)
colnames(tibia_outliers_shorter) <- 'TotalArea'
lowhigh <- cbind(467.7,904.6) # These are the values determining which values are low vs. high outliers
# First attempt: Change background color of cells with high values to red
library(tableHTML)
tableHTML(tibia_outliers_shorter, caption = 'Outlier summary') %>%
add_css_caption(css = list(c('color','font-size'),c('darkblue','12px'))) %>%
add_css_conditional_column(conditional = ">", value = lowhigh[2], css = list('background-color','red'), columns = c("TotalArea")) %>%
tableHTML_to_image()
# Second attempt: Add this argument to same tableHTML command, for cell with low values
add_css_conditional_column(conditional = "<", value = lowhigh[1], css = list('background-color','lightblue'), columns = c("TotalArea")) %>%
There are two things going on here.
You don't have numbers, your TotalArea
column is strings. Your use of rbind("",427.3,978.3, ...)
is incorrect, whomever suggested that way of making vectors or columns, discard it (and perhaps take other things they say with a grain of salt). Since you have mixed strings and numbers, they are all strings. Use NA
for emptiness.
There are a couple of ways around this: use NA
instead of ""
, and your numbers will remain numbers. Also, rbind
just isn't necessary here, include them in the data.frame
call.
tibia_outliers_shorter <- data.frame(
TotalArea = c(NA,427.3,978.3,NA,423.2,967.4,NA,1042.9,NA),
row.names = patients
)
Unfortunately, this causes a problem, since tableHTML
is broken wrt NA
values:
Warning in attributes$header : partial match of 'header' to 'headers'
Error in if (condition[i - 1]) { : missing value where TRUE/FALSE needed
The warning is sloppy, the error is a bug.
I think you need to file a bug report with the maintainer. For instance, I can get the above to work when I remove the NA
values completely:
subset(tibia_outliers_shorter, !is.na(TotalArea)) |>
tableHTML(caption = 'Outlier summary') |>
add_css_caption(css = list(c('color','font-size'),c('darkblue','12px'))) |>
add_css_conditional_column(conditional = "<", value = lowhigh[1], css = list('background-color','red'), columns = "TotalArea")
# Warning in attributes$header : partial match of 'header' to 'headers'
The error missing value where TRUE/FALSE needed
is a classic error when an if
statement produces NA
(see Error in if/while (condition) {: missing Value where TRUE/FALSE needed). I think your sample data and code here are sufficient for the maintainer to be able to reproduce it, and the fix is just simple code to check for missing values instead of blindly assuming everything is non-NA
.
(BTW, tableHTML(..., replace_NA="")
does not fix the issue.)
(Perhaps the author can fix the warning, too. It is informed by issuing options(warnPartialMatchAttr=TRUE)
, a must-have for defensive programming. IMHO those kind of warnings should be mandatory for submitting to CRAN ... but then again, some base packages also emit that warning, so nobody's perfect :-)