0

I am using ggvis and have the following code with a selectInput on the UI side allowing the user to select which variable dictates fill and shape (inputId is fill and shape respectively). I want the plot to have the ability to have a constant fill or shape should the user choose. The else section of this code works exactly how I want, but when I select the option in the if statement the app crashes with the following error:

Error in eval: could not find function ":="

I know I have the syntax correct because if I suppress the legends and the if/else statement and specify the fill as constant (fill := "black") it works how I want it to.

Any help would be appreciated.

vis <- reactive({
fillvar <- prop("fill", as.symbol(input$fill))
shapevar <- prop("shape", as.symbol(input$shape))
filteredData() %>%
ggvis(x = xvar, y = yvar) %>%
  layer_points(size.hover := 200,
               fillOpacity:= 0.5, fillOpacity.hover := 1,

               # Allows for points to be consistent if the user desires

               if (input$fill == "All Points Black") {
                 fill := "black"}
               else {
                 fill = fillvar}
               ,

               if (input$shape == "All Points Circles") {
                 shape := "circle"}
               else {
                 shape = shapevar}
              ,

               key := ~ID
  ) %>%

  # Adds legends to the Plot in designated locations
  add_legend("fill", title = as.character(fillvar)) %>%
  add_legend("shape", title = as.character(shapevar), properties = legend_props(legend = list(y=300))) %>%

  # Adds the previously defined tool_tip my_tooltip
  add_tooltip(my_tooltip, "hover") %>%

  # Specifies the size of the plot
  set_options(width = 800, height = 400, duration = 0)
})

#Actually plots the data
vis %>% bind_shiny("plot1")
User247365
  • 665
  • 2
  • 11
  • 27
  • If you can extract the if/else logic before the ggvis statement to two variables, then it should work. – Xiongbing Jin Jul 02 '16 at 00:16
  • @warmoverflow This did not work. If I place the if else statements outside ggvis, it still gives the same error when the constant option is selected. – User247365 Jul 05 '16 at 15:27
  • You might try your logic outside ggvis and also before using `prop`. Make a variable that is either the mapping variable, `as.name(input$fill)` OR `"black"` based on your logic. Pass this new variable to `prop` within `layer_points`, e.g., `prop("fill", newvar)` and avoid `:=` all together. – aosmith Jul 05 '16 at 20:23
  • @aosmith I figured out how to make the code function as I want if I suppress the legend. However, if the data visualization is set to anything other than the user specified "All Points Black" or "All Points Circles" I still want the legend to display. Any input on this? I am adding a revision to my original post to reflect the updated code. – User247365 Jul 05 '16 at 23:52
  • The legend is added if the `fillvar` is a variable and not added if `fillvar` is a constant, so you don't need `add_legend` at all. If it's not working (maybe because you have two legends?), try adding a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) to your question so folks can take a look at things. Also, rather than updating your question you can write an answer showing how you solved your problem and ask a new question for a new problem. – aosmith Jul 06 '16 at 14:25
  • @aosmith Yes I do have two legends (fill and shape) and they overlap when I do not specify add_legend. I will take your suggestion into account for the future – User247365 Jul 06 '16 at 16:29

2 Answers2

1

As I mentioned in a comment, you can create a variable for prop using an if statement. This allows you to bypass the issue of := by using either a constant or a variable directly in prop.

You get legends automatically. To control the placement when you have two legends (which will lead to an overlap), you can name your ggvis graph. This allows you to refer to add elements to the graphic in order to move the second legend down only when it is added based on logic and your shapevar and fillvar values.

Here's the code just for the reactive function.

vis <- reactive({
    fillvar = "black"
    if(input$fill != "All Points Black") {
        fillvar = as.name(input$fill)
    }

    shapevar = "circle"
    if(input$shape != "All Points Circles") {
        shapevar = as.name(input$shape)
    }

    p1 = filteredData() %>%
        ggvis(x = xvar, y = yvar) %>%
        layer_points(size.hover := 200,
                   fillOpacity:= 0.5, fillOpacity.hover := 1,
                   prop("fill", fillvar),
                   prop("shape", shapevar),
                   key := ~ID
        ) %>%

        # Adds the previously defined tool_tip my_tooltip
        add_tooltip(my_tooltip, "hover") %>%

        # Specifies the size of the plot
        set_options(width = 800, height = 400, duration = 0)


    # Control addition of second legend using if() on p1 object
    if(fillvar != "black" & shapevar != "circle") {
        p1 %>% add_legend("shape", properties = legend_props(legend = list(y=300)))
    }
    else {
        p1
    }

})
aosmith
  • 34,856
  • 9
  • 84
  • 118
0

The code now is functional with input from @aosmith as I want it to be if the legend is suppressed. However, when I do this, the legend for fill and shape overlap as this post addresses.

legends on ggvis graph are overlaping when using tooltip

The fix for that is to add in a legend which makes the plot disappear if the constant data visualization option is selected. I will post a new question to try and get this issue resolved.

UPDATE: The answer below solves the original issue, but @aosmith's answer fixed a second issue that arose after correcting the first issue as well.

My code with the corrected original issue, but containing an overlapping legend (corrected with @aosmith's answer) is below.

vis <- reactive({

  # Allows for points to be consistent if the user desires
  if (input$fill == "All Points Black") {
    fillvar = "black"}
  else {
    fillvar <- as.symbol(input$fill)}

  if (input$shape == "All Points Circles") {
    shapevar = "circle"}
  else {
    shapevar <- as.symbol(input$shape)}

#Plot Data with Visualization Customization
xvar <- prop("x", as.symbol(input$x))
yvar <- prop("y", as.symbol(input$y))

filteredData() %>%
  ggvis(x = xvar, y = yvar) %>%
  layer_points(size.hover := 200,
               fillOpacity:= 0.5, fillOpacity.hover := 1,
               prop("fill", fillvar),
               prop("shape", shapevar),
               key := ~Shot_ID
  ) %>%

  # Adds the previously defined tool_tip my_tooltip
  add_tooltip(my_tooltip, "hover") %>%

  # Specifies the size of the plot
  set_options(width = 800, height = 450, duration = 0)
})

#Actually plots the data
vis %>% bind_shiny("plot1")
Community
  • 1
  • 1
User247365
  • 665
  • 2
  • 11
  • 27