Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R datatable search option doesn't handle exotic encoding (latin1)

Tags:

r

dt

shiny

I've been trying to develop an R Shiny webapp using DT to display a datatable. I need to use an input to fill the datatable search option as I'm filtering and ordering the possibles search-terms by term-freq. My data is in french, therefore it includes accents with latin1 encoding (I tried UTF8 encoding but the rendering gets messy).

I compared renderDataTable behaviours in server-side computing and client-side computing. The client-side works well, but the data is to large to be handled that way. The server-side finds no match for accentuated terms (french accents).

Here is a repex

library(shiny)
library(DT)
data=data.frame(index=1:6,nom=c("hého","bonjour","enchanté","merci","où ça ?","à qui s'adresse-t-il ?"),stringsAsFactors = F)

ui <- fluidPage(
  title = 'Use the DT package in shiny',
  selectizeInput(inputId = 'tag',label="mots pour filtrer",
                 choices=strsplit(data$nom,split = " ")%>%unlist%>%unique),  
  h3('A Table Using Client-side Processing'),
  fluidRow(
    DT::dataTableOutput('tbl_a')
  ),
  h3('A Table Using Server-side Processing'),
  fluidRow(
    DT::dataTableOutput('tbl_b')
  )
)
server <- function(input, output, session) {
  output$tbl_a = DT::renderDataTable(datatable(data,options=list(search=list(search=input$tag))), server = FALSE)
  output$tbl_b = DT::renderDataTable(datatable(data,options=list(search=list(search=input$tag))))
}


shinyApp(ui,server)

Client-side Processing returns the desired result... But I'd like to achieve that with server-side processing.

Here is the output of a call to xfun::session_info('DT')

R version 3.5.3 (2019-03-11)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 17134), RStudio 1.2.1330

Locale:
  LC_COLLATE=French_France.1252 
  LC_CTYPE=French_France.1252   
  LC_MONETARY=French_France.1252
  LC_NUMERIC=C                  
  LC_TIME=French_France.1252    

Package version:
  assertthat_0.2.1  
  BH_1.69.0.1       
  cli_1.1.0         
  colorspace_1.4.1  
  crayon_1.3.4      
  crosstalk_1.0.0   
  digest_0.6.18     
  DT_0.5            
  fansi_0.4.0       
  ggplot2_3.1.0     
  glue_1.3.1        
  graphics_3.5.3    
  grDevices_3.5.3   
  grid_3.5.3        
  gtable_0.3.0      
  htmltools_0.3.6   
  htmlwidgets_1.3   
  httpuv_1.5.0      
  jsonlite_1.6      
  labeling_0.3      
  later_0.8.0       
  lattice_0.20.38   
  lazyeval_0.2.2    
  magrittr_1.5      
  MASS_7.3.51.1     
  Matrix_1.2.15     
  methods_3.5.3     
  mgcv_1.8.27       
  mime_0.6          
  munsell_0.5.0     
  nlme_3.1.137      
  pillar_1.3.1      
  pkgconfig_2.0.2   
  plyr_1.8.4        
  promises_1.0.1    
  R6_2.4.0          
  RColorBrewer_1.1.2
  Rcpp_1.0.1        
  reshape2_1.4.3    
  rlang_0.3.2       
  scales_1.0.0      
  shiny_1.2.0       
  sourcetools_0.1.7 
  splines_3.5.3     
  stats_3.5.3       
  stringi_1.4.3     
  stringr_1.4.0     
  tibble_2.1.1      
  tools_3.5.3       
  utf8_1.1.4        
  utils_3.5.3       
  viridisLite_0.3.0 
  withr_2.1.2       
  xtable_1.8.3      
  yaml_2.2.0     
like image 981
phileas Avatar asked Apr 08 '19 13:04

phileas


1 Answers

Applying iconv(to="UTF-8") to input$tag fixes it !

Check-out the third table tbl_c.

xfun::session_info('DT')
library(shiny)
library(DT)
data=data.frame(index=1:6,nom=c("hého","bonjour","enchanté","merci","où ça ?","à qui s'adresse-t-il ?"),stringsAsFactors = F)

ui <- fluidPage(
  title = 'Use the DT package in shiny',
  selectizeInput(inputId = 'tag',label="mots pour filtrer",
                 choices=strsplit(data$nom,split = " ")%>%unlist%>%unique),  
  h3('A Table Using Client-side Processing'),
  fluidRow(
    DT::dataTableOutput('tbl_a')
  ),
  h3('A Table Using Server-side Processing'),
  fluidRow(
    DT::dataTableOutput('tbl_b')
  ),
  h3('A Table Using Server-side Processing'),
  fluidRow(
    DT::dataTableOutput('tbl_c')
  )
)
server <- function(input, output, session) {
  output$tbl_a = DT::renderDataTable(datatable(data,options=list(search=list(search=input$tag))), server = FALSE)
  output$tbl_b = DT::renderDataTable(datatable(data,options=list(search=list(search=enc2native(input$tag),regex=T))))
  output$tbl_c = DT::renderDataTable(datatable(data,options=list(search=list(search=iconv(input$tag,to = "UTF-8"),regex=T))))
}


shinyApp(ui,server)
like image 165
phileas Avatar answered Oct 11 '22 12:10

phileas