Search code examples
rggvis

ggvis error: (list) object cannot be coerced to type 'double'


I wish to choose what cylinder types to be presented in the plot. Hadley Wickham suggested the following code in https://groups.google.com/forum/#!topic/ggvis/AJZCdjFcNaE

library(ggvis)
mtcars %>% 
 ggvis(~mpg, ~wt) %>% 
 filter(cyl %in% eval(input_checkboxgroup(cyl, selected = '4'))) %>% 
 layer_points(fill = ~cyl) 

It still throws an error:

(list) object cannot be coerced to type 'double'

What list exactly is hidding in there that can not be coerced to 'double' vector?


Solution

  • You are evaluating the result of input_checkboxgroup which returns a list. So the issue is there, the list for some reason cannot be created. Since you are not getting any options to select from (no selection input in your graph) there is no way to evaluate the result of input_checkboxgroup.

    My crude way of correcting the code would be:

    library(dplyr)    
    library(ggvis)
    
    mtcars %>% 
      ggvis(~mpg, ~wt) %>% 
      filter(cyl %in% eval(input_checkboxgroup(choices=unique(mtcars$cyl), 
        selected = "4"))) %>% 
      layer_points(fill = ~cyl) 
    

    In other words, make the choices a list of unique values so that they can be displayed and made available for selection.

    Finding what list is hiding where

    If you look at your code line by line you see the following:

    library(ggvis)
    

    You only have the ggvis library loaded (so if there is anything else that we do not think might be in ggvis we can start looking for missing packages).

    mtcars %>% 
    

    mtcars is the data frame used to make the plot. There is no assignment of any kind. At this point it makes sense to check the headers of your data frame to interpret the rest, for instance: colnames(mtcars) or str(mtcars).

      ggvis(~mpg, ~wt) %>% 
    

    Ok, so the graph will be based on mpg and wt. Both are in the dataframe (we know from the step above) so there should be no issue there. You can also recognize the last line layer_points(fill = ~cyl) as a ggvis instruction, and we do have cyl as a column in the dataframe.

    So that leaves us with the line that says filter(...). And that should be no surprise because the full error that is thrown is:

    Error in filter(., cyl %in% eval(input_checkboxgroup(cyl, selected = "4"))) : 
      (list) object cannot be coerced to type 'double'
    

    If you look at the line itself:

    filter(cyl %in% eval(input_checkboxgroup(cyl, selected = '4'))) %>% 
    

    You might recognize that filter is not a ggvis function. And if not you can check the help pages for ggvis with ?ggvis and go to the index. You will see no filter function listed there. So now you know that there is function missing. The source for that function could be package or function defined somewhere else in the code you are working on.

    We also know that the result from filter is based on an interactive element (input_checkboxgroup) in the ggvis plot. And we know that the result cannot be evaluated because we see no plot.

    So if you factor out any ggvis related items, you would get a little piece of code like so:

    selected_cyl <- mtcars %>%
      filter(cyl %in% '4')
    

    Which in turn throws the error:

    Error in match(x, table, nomatch = 0L) : object 'cyl' not found
    

    Makes sense, right? Because in fact we have not defined cyl anywhere. We know it is a column in the data frame though.

    It is always likely that in an example like this the function will be from either dplyr or tidyr. Most current code will use either of those. Other than that it is a little bit difficult to know exactly. Searching through all function names on CRAN (with the package sos using `sos::findFn("filter") will not give you the answer, unfortunately. In the dplyr documentation "filter" is somewhat hidden in the section on window functions.

    In our case adding dplyr will make it work:

    library(dplyr)
    selected_cyl <- mtcars %>%
      filter(cyl %in% '4')
    

    Now back to the code we started with, but with dplyr loaded as a package. We get a new error:

    Error in lapply(obj, function(val) { : object 'cyl' not found
    

    Looks a lot like the one we just corrected above, only instead of an error in match we now have an error in lapply. We also know that the first reference to cyl is found correctly (using the dplyr pipe-substitution). So it must be in the second cyl where the problem lies.

    To populate input_checkboxgroup we need a list of values with the selection (your "hidden list" that prompted this question). The dplyr style piping for some reason does not work here, so we must specify that we mean cyl to be a column from the mtcars data frame. For example:

    filter(cyl %in% eval(input_checkboxgroup(mtcars$cyl, 
                                               selected = "4"))) %>% 
    

    If you include that line however, the full row of cyl will show up as an input option, with all the occurences of 4 selected. But it will run now. So the only thing missing is to make the values offered for selection unique:

    filter(cyl %in% eval(input_checkboxgroup(choices = unique(mtcars$cyl), 
      selected = "4"))) %>%
    

    And now you have the corrected code as above, and you know that the "list" in the first error was the list expected by `input_checkboxgroup' that could not be evaluated, and as it did not exist on running the code and hence could not be coerced to double.