rhandsontable icon indicating copy to clipboard operation
rhandsontable copied to clipboard

hot_to_r coerce logical to integers

Open bartekch opened this issue 3 years ago • 0 comments

In some cases hot_to_r does not convert logical type correctly and returns integer instead. The following example shows different cases. Returned type is incorrect when logical column is paired only with numeric, without character columns (second case). Adding character column seems to help (third case), but no when all values are missing (fourth case). I would say it's pretty surprising behaviour.

shinyApp(
  ui = basicPage(
    tagList(
      h4("Logical"),
      rhandsontable::rHandsontableOutput("t1"),
      verbatimTextOutput("o1"),
      
      h4("Numeric + logical"),
      rhandsontable::rHandsontableOutput("t2"),
      verbatimTextOutput("o2"),
      
      h4("Numeric + logical + character"),
      rhandsontable::rHandsontableOutput("t3"),
      verbatimTextOutput("o3"),
      
      h4("Numeric + logical + NA_character"),
      rhandsontable::rHandsontableOutput("t4"),
      verbatimTextOutput("o4")
    )
  ),
  
  server = function(input, output, session) {
    output$t1 <- rhandsontable::renderRHandsontable({
      rhandsontable::rhandsontable(
        data.frame(
          logical = FALSE
        )
      )
    })
    output$o1 <- renderPrint({
      str(rhandsontable::hot_to_r(input$t1))
    })
    
    
    output$t2 <- rhandsontable::renderRHandsontable({
      rhandsontable::rhandsontable(
        data.frame(
          logical = FALSE,
          numeric = 0
        )
      )
    })
    output$o2 <- renderPrint({
      str(rhandsontable::hot_to_r(input$t2))
    })
    
    
    output$t3 <- rhandsontable::renderRHandsontable({
      rhandsontable::rhandsontable(
        data.frame(
          logical = FALSE,
          numeric = 0,
          character = ""
        )
      )
    })
    output$o3 <- renderPrint({
      str(rhandsontable::hot_to_r(input$t3))
    })
    
    
    output$t4 <- rhandsontable::renderRHandsontable({
      rhandsontable::rhandsontable(
        data.frame(
          logical = FALSE,
          numeric = 1,
          character = NA_character_
        )
      )
    })
    output$o4 <- renderPrint({
      str(rhandsontable::hot_to_r(input$t4))
    })
    
  }
)

I think that the problem is with type.convert function used inside colClasess, as it is not working as it is expected here. type.convert(0, as.is = TRUE) returns 0 and not FALSE. The reason that it works when there is some character column is that we pass "FALSE" to type.convert which indeed returns logical value. And of cource type.convert(FALSE, as.is = TRUE) == FALSE.

Why there are different values at all is caused by the fact, that inside toR the whole table is turned into vector and therefore coerced to the same type. In the examples:

> unlist(list(FALSE))
# FALSE                     # logical
> unlist(list(FALSE, 0))
# 0 0                          # numeric
> unlist(list(FALSE, 0, ""))
# "FALSE" "0" ""         # character
> unlist(list(FALSE, 0, NULL))
# 0 0                          # numeric

I think that the problem should be solved by calling as.logical inside colClasses instead of type.convert, I haven't found any issues with such a solution so far. I'd be happy to make pull request.

bartekch avatar Jan 25 '22 18:01 bartekch