user3577904
user3577904

Reputation: 491

Error: First argument must be a data frame or shared data

I want to create dynamic plots based selectorInput in shinydashboard, but when I want to create plot I get error:

First argument, data, must be a data frame or shared data.

Here is part of my code is Server part when I try to subset data and use them as plotly input:

data_sub = reactive({
data_sub_temp = df[df$market == input$market_selector,]
return(data_sub_temp)
  })


  output$market_plot <- renderPlotly({
  plot_ly(
  data = data_sub,
  x = ~ created,
  y = ~ pax,
  group_by = ~ type,
  color = ~ type,
  type = "scatter",
  mode = "lines+markers",
  hoverinfo = 'text',
  text = ~ paste('Year:', created,
                 '</br> </br> Clients: ', pax)
  )  
  })

Dataset is loaded and pre-processed before UI&Server code part. When I use dataset subsetted before UI&Server part this code works, I am unable to maket it work when data_sub part is added. Any suggestion? Thanks

Upvotes: 1

Views: 6411

Answers (3)

Abdelah
Abdelah

Reputation: 9

try to use data = data_sub() instead of data = data_sub

output$market_plot <- renderPlotly({
  plot_ly(
  data = data_sub(),
  x = ~ created,
  y = ~ pax,
  group_by = ~ type,
  color = ~ type,
  type = "scatter",
  mode = "lines+markers",
  hoverinfo = 'text',
  text = ~ paste('Year:', created,
                 '</br> </br> Clients: ', pax)
  )  
  })

Upvotes: 0

Justin.Mathew
Justin.Mathew

Reputation: 481

Reactive is used to limit what gets re-run during a reaction. The reactive({}) expression creates reactions similar to input$... expressions.

I.e in your example pulling data_sub out of the renderPlotly() expression would prevent renderPlotly from running when df$market or input$market_selector change unless you tell shiny that data_sub must be reactive as you have done above. There is little point in isolating data_sub from your renderPlotly() expression unless other input$... expressions were causing renderPlotly() to redraw. See Reactive Tutorial for a better understanding.

If you wish to keep data_sub reactive you need to call it using the bracket notation in your plot. I.e data = data_sub()

It may also be useful to get a grip on assignment operators in R as you are using the = operator incorrectly. Your code will still run however it is better to use the <- operator for data_sub. See Difference between assignment operators in R.

The final code should look something like:

Server

data_sub <- reactive({df[df$market == input$market_selector,]})

output$market_plot <- renderPlotly({
  plot_ly(
  data = data_sub(),
  x = ~ created,
  y = ~ pax,
  group_by = ~ type,
  color = ~ type,
  type = "scatter",
  mode = "lines+markers",
  hoverinfo = 'text',
  text = ~ paste('Year:', created,
                 '</br> </br> Clients: ', pax)
  )  
})

Upvotes: 0

Barbara
Barbara

Reputation: 1168

I think that the problem is that the dataframe part is reactive, but not the plot. You can try using an eventHandler instead. In this case, you need to add an actionButton in the ui (possibly in the sidebarPanel) and add the eventHandler in the server, without the reactive part. Code below.

ui

 actionButton(
      inputId = "submit_loc",
      label = "Submit")

server

observeEvent(
    eventExpr = input[["submit_loc"]],
    handlerExpr = {

data_sub <- df[df$market == input$market_selector,]

output$market_plot <- renderPlotly({
  plot_ly(
  data = data_sub,
  x = ~ created,
  y = ~ pax,
  group_by = ~ type,
  color = ~ type,
  type = "scatter",
  mode = "lines+markers",
  hoverinfo = 'text',
  text = ~ paste('Year:', created,
                 '</br> </br> Clients: ', pax)
  )  
  })

})

Try and let me know whether this works.

Upvotes: 4

Related Questions