Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradient colored datatable rows in R Shiny

Tags:

r

dt

shiny

I was wondering if we could do this in R Shiny example

# using styleColorBar
datatable(df) %>% formatStyle(names(df),
  background = styleColorBar(range(df), 'lightblue'),
  backgroundSize = '98% 88%',
  backgroundRepeat = 'no-repeat',
  backgroundPosition = 'center')

enter image description here

But with two colors for positive and negative values and moreover if we can do so the negative values are taken as absolute values for the length of the bar

Ty and have a good day !

like image 581
tricky Avatar asked Jul 08 '16 10:07

tricky


1 Answers

You can do it manually using rowCallback

as you can see

sss=datatable(df) %>% formatStyle(names(df),
                              background = styleColorBar(range(df), 'lightblue'),
                              backgroundSize = '98% 88%',
                              backgroundRepeat = 'no-repeat',
                              backgroundPosition = 'center')


sss$x$options$rowCallback

Generate for each column :

function(row, data) { var value=data[ 1]; if (value!==null) $(this.api().cell(row, 1).node()).css({'background':isNaN(parseFloat(value)) || value <= -1.311 ? '' : 'linear-gradient(90deg, transparent ' + (2.199 - value)/3.51 * 100 + '%, lightblue ' + (2.199 - value)/3.51 * 100 + '%)','background-size':'98% 88%','background-repeat':'no-repeat','background-position':'center'});

So :

1) You need to calc range variables:

rr=range(df)[2]-range(df)[1]
r1=range(df)[2]
r0=range(df)[1]

2) Than use it in rowCallback

  datatable(
  df,  
  options = list(
        rowCallback=JS(paste0("function(row, data) {",
                              paste(lapply(1:ncol(df),function(i){
                                paste0("var value=data[",i,"];
                                       if (value!==null){
                                       if(value<0){
                                       $(this.api().cell(row,",i,").node()).css({'background':isNaN(parseFloat(value)) || value <=",r0," ? '' : 'linear-gradient(90deg, transparent ' + (",r1," - value)/",rr," * 100 + '%, red ' + (",r1," - value)/",rr," * 100 + '%)','background-size':'98% 88%','background-repeat':'no-repeat','background-position':'center'});
                                       }else{
                                       $(this.api().cell(row,",i,").node()).css({'background':isNaN(parseFloat(value)) || value <=",r0," ? '' : 'linear-gradient(90deg, transparent ' + (",r1," - value)/",rr," * 100 + '%, lightblue ' + (",r1," - value)/",rr," * 100 + '%)','background-size':'98% 88%','background-repeat':'no-repeat','background-position':'center'});
                                       }
                                       } ") 
}),collapse="\n"),
"}"))
  )
) 

Here I hard coded colors (red and lightblue)

Result enter image description here

If you want different length for positive and negative you need different range variable or using abs\ Math.abs - for absolute value (for var in JS and for ranges)

Ps

Numeration for columns in JS started from 0 so if you havent rownames you need 0:(ncol(df)-1) in lapply for right result

Update

Range -1 :1 and color scale for abs value

df = as.data.frame(cbind(matrix(round(runif(50, -1, 1), 3), 10), sample(0:1, 10, TRUE)))


rr=range(abs(df))[2]-range(abs(df))[1]
r1=range(abs(df))[2]
r0=range(abs(df))[1]



datatable(
  df,  
  options = list(
        rowCallback=JS(paste0("function(row, data) {",
                              paste(lapply(1:ncol(df),function(i){
                                paste0("var value=Math.abs(data[",i,"]);
                                        var value2=data[",i,"];
                                       if (value!==null){
                                       if(value2<0){
                                       $(this.api().cell(row,",i,").node()).css({'background':isNaN(parseFloat(value)) || value <=",r0," ? '' : 'linear-gradient(90deg, transparent ' + (",r1," - value)/",rr," * 100 + '%, red ' + (",r1," - value)/",rr," * 100 + '%)','background-size':'98% 88%','background-repeat':'no-repeat','background-position':'center'});
                                       }else{
                                       $(this.api().cell(row,",i,").node()).css({'background':isNaN(parseFloat(value)) || value <=",r0," ? '' : 'linear-gradient(90deg, transparent ' + (",r1," - value)/",rr," * 100 + '%, lightblue ' + (",r1," - value)/",rr," * 100 + '%)','background-size':'98% 88%','background-repeat':'no-repeat','background-position':'center'});
                                       }
                                       } ") 
}),collapse="\n"),
"}"))
  )
) 

enter image description here

like image 119
Batanichek Avatar answered Oct 10 '22 05:10

Batanichek