Shiny: how to use a dataframe as an input for an interactive graph

Hello! I'm a beginner in R and Shiny. I have to create an interactive graph, which gives the opportunity to select a "ZONE" and returns back the corresponding graph.

I have created a function that does this job. By using as an argument the ZONE you are interested in, it creates the corresponding graph.

To make it interactive, I'm trying to build a shiny app. I have put inside the server the function and inside UI the names of the ZONEs as inputs.
The problem is that the app doesn't display any plot. I think it should be due to the fact that shiny app is not uploading the dataframe, which should be stored in R memory because of the previous chunks.
Below my code. I attach both the function and the shiny app code.
Thanks in advance.

Function (well functioning alone)

demand_supply = function(zone = "ZONENAME"){
  zone_sup = dataframe %>% filter(ZONE_CD == zone ) %>% filter(PURPOSE_CD == "OFF") %>% filter(ENERGY_PRICE_NO != "0.00") %>% select(QUANTITY_NO, ENERGY_PRICE_NO)
  
  zone_sup$QUANTITY_NO = as.numeric(zone_sup$QUANTITY_NO)
  zone_sup$ENERGY_PRICE_NO = as.numeric(zone_sup$ENERGY_PRICE_NO)
  
  plot_sup = zone_sup %>% 
  ggplot(aes(QUANTITY_NO,ENERGY_PRICE_NO))+
  geom_point()+
  geom_smooth(method = lm)+
  labs(x = "Quantity", y = "Price")+
  theme_minimal()

  zone_dem = dataframe %>% filter(ZONE_CD == zone) %>% filter(PURPOSE_CD == "BID")  %>%
    select(QUANTITY_NO, ENERGY_PRICE_NO)%>% filter(ENERGY_PRICE_NO != "0.00")
  
  zone_dem$QUANTITY_NO = as.numeric(zone_dem$QUANTITY_NO)
  zone_dem$ENERGY_PRICE_NO = as.numeric(zone_dem$ENERGY_PRICE_NO)
  
  #zone_dem = zone_dem %>% filter(QUANTITY_NO < 110) #I remove some outliers
  
  plot_dem = zone_dem %>% 
  ggplot(aes(QUANTITY_NO,ENERGY_PRICE_NO))+
  geom_point()+
  geom_smooth(method = lm)+
  labs(x = "Quantity", y = "Price")+
  theme_minimal()
  
  return(ggarrange(plot_sup, plot_dem, labels = c("Supply", "Demand"), font.label= list(size = 10), hjust = -1))
  }

Shiny app (just displaying the SideBar):

ui = function(request){
  
  pageWithSidebar(
    headerPanel("Interactive Supply and Demand"),
    
   
    sidebarPanel(
      selectInput("ZONE", "Please Select the Zone",
                  choices = c("NORD", "CNOR", "CSUD", "SUD", "CALA", "SICI", "SARD"))
    ),
    
    mainPanel(
      plotOutput("myPlot")
    )
  )
}
server = function(input, output, session){
    renderPlot(demand_supply(zone = input$ZONE))
  }
shinyApp(ui = ui, server = server)

You placed an output myPlot but didn't associate it with a renderPlot, though you have one just seems you didn't assign it to output$myPlot

1 Like

Thank you for the answer!
I have added output$myplot as you have suggested but it continues to create an app with no plot.
I've also tried to modify the function so that it has the dataframe as argument and I have inserted a read function inside the rendplot.

Now a graph appears but without data, only the title and the labs of the axis. I attach a screenshot

Here my code

server = function(input, output, session){
    output$myPlot = renderPlot({
      df = read.csv("df.csv")
      z = toString(input$zone)
      demand_supply(dataf = df, zone = z)
      })
  }

Please, any suggestion is more than welcome!!

plot|690x420

Hi, welcome!

To help us help you, could you please prepare a reproducible example (reprex) illustrating your issue? Please have a look at these resources, to see how to create one for a shiny app

1 Like

Thank you for your availability and I'm sorry for being short. I'm new in this forum.
Here my reprex:
Thanks in advance and hope you'll find it helpful to help me :slight_smile:

library(depmixS4)
library(ggrepel)
library(tidyverse)
library(ggplot2)
library(tidyr)
library(ggpubr)
library(shiny)
#DATASET
d = data.frame(Zone = c("NORD", "NORD", "NORD", "NORD", "SOUTH","NORD", "NORD", "NORD", "NORD", "SOUTH"), Purpose = c("OFF", "OFF", "OFF", "OFF", "OFF", "BID", "BID", "BID", "BID", "BID"), Price = c("10", "15", "20", "25", "30", "10","15", "20", "25", "30"), Quantity = c("100", "200", "300", "400","500", "500", "400", "300", "200", "100"))

#FUNCTION TO USE INSIDE THE SERVER
dem_sup = function(zone = "ZONE"){
  sup = d %>% filter(Zone == zone ) %>% filter(Purpose == "OFF") %>% select(Quantity, Price)
  
  sup$Quantity = as.numeric(sup$Quantity)
  sup$Price = as.numeric(sup$Price)
  
  plot_sup = sup %>% ggplot(aes(Quantity, Price))+ geom_point() + geom_smooth(se=FALSE, col = "orange")+ geom_smooth(method=lm, se=FALSE, col="green") + labs(x = "MWh", y = "Euro/MWh")+ theme_minimal()
  
  dem = d %>%  filter(Zone == zone) %>% filter(Purpose == "BID") %>% select(Quantity, Price)
  
  dem$Quantity = as.numeric(dem$Quantity)
  dem$Price = as.numeric(dem$Price)
  
  plot_dem = dem %>% ggplot(aes(Quantity,Price))+geom_point()+geom_smooth(se=FALSE, col = "orange")+geom_smooth(method= lm, se = FALSE, col = "green")+labs(x="MWh", y="Euro/MWh")+ theme_minimal()
  
  return(ggarrange(plot_sup, plot_dem, labels = c("Supply", "Demand"), font.label= list(size = 10), hjust = -1)) 
}        

#UI
ui = function(request){
  
  pageWithSidebar(
    headerPanel("Interactive Supply and Demand"),
    
    
    sidebarPanel(
      selectInput("ZONE", "Please Select the Zone",
                  choices = c("NORD", "SOUTH"))
    ),
    
    mainPanel(
      plotOutput("myPlot")
    )
  )
}

#SERVER
server = function(input, output, session){
  output$myPlot = renderPlot({
    z = toString(input$zone)
    dem_sup(zone = z)
  })
}

shinyApp(ui = ui, server = server)

r is a case sensitive language.
when you set the input

selectInput("ZONE"

that means you would access it with
input$ZONE rather than input$zone

Problem solved! I'm sorry for the trivial mistakes, I'll be more diligent from now on.
Anyway, it was a good exercise for me to write a reprex.
Thank you for your help!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.