Issue:
I'm interested in displaying three graphs in a shiny web app. I have written three functions to graph each type of plot for a specified range. The function's parameter takes a input parameter, region, and subsets the larger data.frame for that specified region and subsequently graphs it.
I'm having difficulty passing this function into an r-shiny reactive element.
Here is my function:
plot_30cumulative <- function(enter_region) {
subset <<- HPF[HPF$region == enter_region, ]
thirty_year_cumulative <<- ggplot(subset, aes(x=subset$date)) +
geom_line(aes(y = subset$BaseCumulative, color = "Base"), color = "green") +
geom_line(aes(y = subset$StressCumulative, color = "Adjusted"), color = "red", linetype = "dashed") +
theme_bw() +
scale_x_date(name = "",
date_labels = "%Y-%m-%d",
limits = as.Date(c("2014-02-15", "2044-02-15")),
breaks = seq(as.Date("2014-02-15"), as.Date("2044-02-15"), by = "1 year")) +
scale_y_continuous(name = "Cumulative Growth Rates",
breaks = seq(min(subset$StressCumulative),max(subset$BaseCumulative), .25),
limits = c(NA, 4), # Temporarily hard-coded for better visability.
labels = percent) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
ggtitle("Cumulative 30-Year Growth Rates")
What I Want in Shiny:
library(shiny)
#Define UI for dataset
ui <- fluidPage(
#App title ----
titlePanel("Home Price Forecasting under Stress Scenarios"),
sidebarLayout(
sidebarPanel(
#Input: Stress Path Function Parameters ----
#Input: Numeric entry for region to plot ----
numericInput(inputId = "region",
label = "Enter Region Number:",
value = "1",
min = 1,
max = 110)
),
# Main panel for displaying outputs ----
mainPanel(plotOutput(outputId = "ThYrC"),
plotOutput(outputId = "FiYrC"),
plotOutput(outputId = "FoYrQtr")
)
)
)
#Define server logic to summarize and view selected dataset ----
server <- function(input, output){
output$ThYrC <- renderPlot({reactive(plot_30cumulative(enter_region == input$region)}))
}
# Run the application ----
shinyApp(ui = ui, server = server)
Problem:
I can't seem to pass the function parameter, enter_region, to the reactive element by input$region == enter_region.
Any insight into this issue would be much appreciated!
Related
I try to display interactive plots by using R shiny. I can successfully make the GUI and published, but the plots in tabPanel shows nothing, just like the picture shows below. There is the data I used (have been downloaded into my laptop).
I think problem may caused by the way how I preprocessing my data in server.R, but whatever I tried, it still display nothing. No Error shows when I run the app.
enter image description here
My code in ui.R:
library(shiny)
shinyUI(fluidPage(
titlePanel("Data Viz Lab"),
sidebarLayout(
sidebarPanel(
## Add X-Variable select element
selectInput(inputId = "var_x",
label = h5("X-Variable"),
choices = c("Structure.Cost", "Land.Value", "Home.Value", "Home.Price.index"),
selected = "Land.Value"),
## Add Fill Color select element
selectInput(inputId = "color",
label = h5("Fill Color"),
choices = c("brown", "yellow", "green", "blue", "red"),
selected = "brown"),
## Add log-scale check box
checkboxInput(inputId = "log",
label = "log-sclae for X-variable in Scatterplot?",
value = FALSE),
## Add Y-Variable select element
selectInput(inputId = "var_y",
label = h5("Y-Variable"),
choices = c("Structure.Cost", "Land.Value", "Home.Value", "Home.Price.index"),
selected = "Structure.Cost"),
## Add Circle-Size side bar
sliderInput(inputId = "size",
label = h5("Circle-Size"),
min = 1,
max = 10,
value = 3),
## Add Outlier color select element
selectInput(inputId = "color_out",
label = h5("Outlier Color"),
choices = c("white", "yellow", "green", "blue", "red"),
selected = "white")
),
mainPanel(
tabsetPanel( # Establish tabset panel
tabPanel(
# Tab1
title = "Histogram",
value = plotOutput(outputId = "hist") # Add an figure in tab1
),
tabPanel(
# Tab2
title = "Scatterplot",
value = plotOutput(outputId = "scatter") # Add an figure in tab2
)
)
)
)
))
My code in server.R:
library(shiny)
library(ggplot2)
library(sp)
library(dplyr)
# setwd()
landdata = read.csv("landdata.csv")
options(scipen = 999)
shinyServer(function(input, output) {
## Plotting Histogram
output$hist = renderPlot({
# Plotting
if (input$log == FALSE){
ggplot(landdata, aes_string(x = input$var_x)) +
geom_histogram(color = input$color)
}else{
ggplot(landdata, aes_string(x = input$var_x)) +
geom_histogram(color = input$color) +
scale_x_log10(input$var_x)
}
})
## Plotting Scatter plot
output$scatter = renderPlot({
# Data pre-processing
p = ggplot(data = landdata, aes_string(x = input$var_x, y = input$var_y)) +
geom_point() +
stat_ellipse(type = "norm", level = 0.95, color = "black")
build = ggplot_build(p)$data
pts = build[[1]]
elli = build[[2]]
Outlier = point.in.polygon(pts$x, pts$y, elli$x, elli$y)
landdata = cbind(landdata, Outlier)
landdata$Outlier = ifelse(landdata$Outlier == 0, yes = "Y", no = "N") %>% factor(level = c("Y", "N"))
# Plotting
if (input$log == FALSE){
ggplot(landdata, aes_string(x = input$var_x, y = input$var_y)) +
geom_point(aes(color = Outlier), size = input$size) +
scale_color_manual(values = c(input$color, input$color_out))
}else{
ggplot(landdata, aes_string(x = input$var_x, y = input$var_y)) +
geom_point(aes(color = Outlier), size = input$size) +
scale_color_manual(values = c(input$color, input$color_out)) +
scale_x_log10(input$var_x)
}
})
})
The mistake lies in the tabPanel setup. value is not the correct argument for the plot. value is "the value that should be sent when tabsetPanel reports that this tab is selected" (taken from the manual). That means, value has the role of an id (like id argument of tabsetPanel or outputId of plotOutput).
Remove value = to make it work (the code snippet below gave me an output on my system).
tabsetPanel( # Establish tabset panel
tabPanel(
# Tab1
title = "Histogram",
plotOutput(outputId = "hist") # Add an figure in tab1
),
tabPanel(
# Tab2
title = "Scatterplot",
plotOutput(outputId = "scatter") # Add an figure in tab2
)
)
Hello I'm doing this Shiny app for a class project and I was wondering why my graph isn't appearing at all. It runs without giving me an error and shows the side panels, but the graph is appearing blank. I've attached the code below. I've seen other posts on here that deal with us and I've tried them out, but nothing has been giving me the results I need. I just need this to show up by Tuesday, so I can present it on Thursday morning. Thank you!
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
# Load Libraries
library(shiny)
library(tidyverse)
library(ggrepel)
library(dplyr)
library(magrittr)
library(quantmod)
# Load and Merge Data
wordbank = read_csv("/Users/Dohyun/Desktop/school stuff/year3/stat41/final project/administration_data.csv")
wordbank
# Define UI
ui <- fluidPage(
# Application title
titlePanel("Word Bank"),
# Sidebar layout with a input and output definitions
sidebarLayout(
# Inputs: Select variables to plot
sidebarPanel(
selectInput(inputId = "x",
label = "X-axis:",
choices = c("Age" = "age")),
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("Word Size" = "comprehension")),
selectInput(inputId = 'language', 'Language: ',
choices = c("English (American)", "English (British)", "English (Australian)",
"American Sign Language","British Sign Language",
"Cantonese","Croatian","Czech", "Danish", "French (French)",
"French (Quebecois)", "German", "Greek (Cypriot)", "Hebrew",
"Italian", "Kigiriama", "Kiswahili", "Korean", "Latvian",
"Mandarin (Beijing)", "Mandarin (Taiwanese", "Norwegian",
"Portugeuse (European)", "Russian", "Slovak", "Spanish (European)",
"Spanish (Mexican)", "Swedish", "Turkish")),
sliderInput(inputId = "alpha",
label = "Alpha:",
min = 0, max = 1,
value = 0.5)
),
#Output
mainPanel(
plotOutput(outputId = "scatterplot"),
plotOutput(outputId = "boxplot"),
br(), # a little bit of visual separation
)
)
)
# Define server function --------------------------------------------
server <- function(input, output) {
lang_data <- reactive({
wordbank %>%
filter(language %in% input$language)
})
# Create scatterplot object the plotOutput function is expecting
output$lang_plot <- renderPlot({
# Creates base plot
p1 <-
ggplot(lang_data(), aes(x = input$x, y = input$y, fill = as.factor(age))) +
geom_boxplot(alpha = .6, outlier.shape = NA) +
geom_jitter(size = 0.2, alpha = input$alpha, width = 0.3, aes(color = as.factor(age))) +
scale_fill_viridis_d(end = .75, option = "D", guide=FALSE) +
scale_color_viridis_d(end = .75, option = "D", guide=FALSE) +
labs(x = str_to_title(str_replace_all(input$x, "_", " ")),
y = str_to_title(str_replace_all(input$y, "_", " "))) +
scale_x_continuous(breaks = seq(from = 16, to = 30, by = 2))
theme(panel.background = element_blank())
print(p1)
})
}
# Create the Shiny app object ---------------------------------------
shinyApp(ui, server)
New to R and Shiny and working on my first little app. The code below works as I want but now I need to extend it so that when it is loaded there is a parameter in the URL (something like http://127.0.0.1:6804/?Sta_ID=1ABIR000.76) which is used in that first query to set the wqmdata data frame. I've figured out how to use the parseQueryString function to grab that parameter out of the URL in the server code block, but I can't figure out how to use it in that initial data load of the wqmdata data frame? That data frame is used to populate a bunch of stuff in the UI which is based on the specific station (i.e. every station can have a different list of monitored water quality parameters).
A little background on what I'm trying to do. Eventually that pl45_wqm_data.csv file will be replaced with a call to a SQL server database to get the data for the app. That database has thousands of monitoring stations with millions of observations so I obviously just want to bring back the data that is needed in that initial call. The idea is to have a URL which can be called from an ArcGIS Portal app so users can use the interactive map (with a bunch of other data) to find a monitoring station then click on the station to launch the R Shiny app to visualize the monitoring data for that station.
Any ideas to try?
library(shiny)
library(ggplot2)
library(tidyverse)
#Get monitoring data
wqmdata <- arrange(subset(read.csv(file="~\\R\\ShinyApps\\WQMGraphURL\\pl45_wqm_data.csv"
, fileEncoding="UTF-8-BOM"),Sta_ID == "1ABIR000.76"),Parameter,Fdt_Date_Time)
# Define UI for application that allows user to select a Parameter then get a graph
ui <- fluidPage(
tags$style(type='text/css',
".selectize-input {font-size: 12px; line-height: 12px;}
.selectize-dropdown {font-size: 11px; line-height: 11px;}"),
# Give the page a title
titlePanel(paste("DEQ Water Quality Monitoring Station Data for ",unique(wqmdata$Sta_ID))),
hr(),
# Generate a row with a sidebar
sidebarLayout(
# Define the sidebar with one input
sidebarPanel(
#dropdown to select parameter to be graphed
selectInput("SelectedParameter", "Select Parameter for Graph:",
choices=unique(wqmdata$Parameter)),
hr(),
# Button
downloadButton("downloadData", "Download Station Data"),
helpText("Download file contains all monitoring data including field data parameters")
),
# Create a spot for the barplot
mainPanel(
plotOutput("ParameterPlot")
)
)
)
# Define server logic required to draw graph
server <- function(input, output, session) {
GraphRecords <- reactive({
filter(wqmdata, Parameter == input$SelectedParameter)
})
GraphRecordsRows <- reactive({nrow(filter(wqmdata, Parameter == input$SelectedParameter))})
# Fill in the spot we created for a plot
output$ParameterPlot <-
renderPlot({
# Render the graph
graph.title <- "Parameter Data Graph"
yaxis.label <- paste(unique(GraphRecords()$Parameter)," Value")
if (GraphRecordsRows() == 1)
{ ggplot(GraphRecords(), aes(Fdt_Date_Time, Parameter_Value, group = 1)) +
geom_point() +
labs(x = "Sample Date", y = yaxis.label, title = graph.title) +
theme(axis.text.x = element_text(angle = 90,vjust = 0.5, hjust = 1)) +
geom_text(aes(label = Parameter_Value), angle = 70, hjust = 0, vjust = -0.5, size = 3) }
else
{ ggplot(GraphRecords(), aes(Fdt_Date_Time, Parameter_Value, group = 1)) +
geom_point() +
geom_line()+
labs(x = "Sample Date", y = yaxis.label, title = graph.title) +
theme(axis.text.x = element_text(angle = 90,vjust = 0.5, hjust = 1)) +
geom_text(aes(label = Parameter_Value), angle = 70, hjust = 0, vjust = -0.5, size = 3) }
})
# Downloadable csv of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
paste(unique(wqmdata$Sta_ID), "_StationData.csv", sep = "")
},
content = function(file) {
write.csv(wqmdata, file, row.names = FALSE)
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
More or less figured it out. I'm getting a 'Warning: Error in : Aesthetics must be either length 1 or the same as the data (1): x, y' error when the page first loads (I guess because the plotOutput runs before there is any data supplied) but I'll figure out how to get that fixed. The whole idea of reactive data in R is very foreign to me but very cool.
Here is the updated code. I still need to clean it up a bit but this works:
library(shiny)
library(ggplot2)
library(tidyverse)
# Define UI for application that allows user to select a Parameter then get a graph
ui <- fluidPage(
tags$style(type='text/css',
".selectize-input {font-size: 12px; line-height: 12px;}
.selectize-dropdown {font-size: 11px; line-height: 11px;}"),
# Give the page a title
titlePanel(textOutput("titleText")),
hr(),
# Generate a row with a sidebar
sidebarLayout(
# # Define the sidebar with one input
sidebarPanel(
#dropdown to select parameter to be graphed
selectInput("graphParameters","Select Parameter for Graph:","graphParameters"),
hr(),
# Button
downloadButton("downloadData", "Download Station Data"),
helpText("Download file contains all monitoring data including field data parameters")
),
# # Create a spot for the barplot
mainPanel(
plotOutput("ParameterPlot")
)
)
)
# Define server logic required to draw graph
server <- function(input, output, session) {
stationidParameter <- reactive({
query <- parseQueryString(session$clientData$url_search)
query[["stationid"]]
})
wqmdata <- reactive({arrange(subset(read.csv(file="~\\R\\ShinyApps\\WQMGraphURL2\\pl45_wqm_data.csv"
, fileEncoding="UTF-8-BOM"),Sta_ID == stationidParameter()),Parameter,Fdt_Date_Time)})
output$titleText <- renderText({paste("DEQ Water Quality Monitoring Station Data for ",unique(wqmdata()$Sta_ID))})
observe({updateSelectInput(session, "graphParameters", choices = unique(wqmdata()$Parameter))})
GraphRecords <- reactive({filter(wqmdata(), Parameter == input$graphParameters)})
GraphRecordsRows <- reactive({nrow(filter(wqmdata(), Parameter == input$graphParameters))})
# Fill in the spot we created for a plot
output$ParameterPlot <-
renderPlot({
# Render the graph
graph.title <- "Parameter Data Graph"
yaxis.label <- paste(unique(GraphRecords()$Parameter)," Value")
if (GraphRecordsRows() == 1)
{ ggplot(GraphRecords(), aes(Fdt_Date_Time, Parameter_Value, group = 1)) +
geom_point() +
labs(x = "Sample Date", y = yaxis.label, title = graph.title) +
theme(axis.text.x = element_text(angle = 90,vjust = 0.5, hjust = 1)) +
geom_text(aes(label = Parameter_Value), angle = 70, hjust = 0, vjust = -0.5, size = 3) }
else
{ ggplot(GraphRecords(), aes(Fdt_Date_Time, Parameter_Value, group = 1)) +
geom_point() +
geom_line()+
labs(x = "Sample Date", y = yaxis.label, title = graph.title) +
theme(axis.text.x = element_text(angle = 90,vjust = 0.5, hjust = 1)) +
geom_text(aes(label = Parameter_Value), angle = 70, hjust = 0, vjust = -0.5, size = 3) }
})
# Downloadable csv of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
paste(unique(wqmdata()$Sta_ID), "_StationData.csv", sep = "")
},
content = function(file) {
write.csv(wqmdata(), file, row.names = FALSE)
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
The following minimal Shiny app fails to display when I launch the app. The sidebar shows up but not the main panel. I get no error messages or warnings. The app just hangs there.
The ggplot works in the console.
This must be an environmental parameter controlling the interface between Shiny & ggplot2. But what is it. Have tried setting dev.off() to no avail. Does anyone have any suggestions?
ui <- fluidPage(
sidebarPanel(
# client logo
# select trade
selectInput(inputId = "trade",
label = "Trade",
choices = trades,
selected = defaultTrade
)
),
mainPanel(
# performance time series plots
plotOutput(outputId = "tsPlotRev", height = "195px")
)
)
server <- function(input, output) {(
output$tsPlotVol <- renderPlot(
ggplot(data.frame(tsData), aes(x = as.Date(weekDate), y = as.numeric(revenue) / 1000000, color = as.factor(isHist))) +
geom_line() + scale_x_date(date_breaks = "4 week", date_labels = "%y-%W") +
theme(axis.text.x = element_text(angle = 45, hjust = 0.75), legend.position = "none") +
labs(x = NULL, y = "revenue (million USD)")
)
)}
shinyApp(ui = ui, server = server)
My ggplotly plot (see Tab 3 in server.R) does not work when used in my Shiny app. However, when I generate the plot by itself in RStudio, it works fine.
This is the bit of code that does not render a plot correctly.
output$facetmap=renderPlotly({
ggplotly(
ggplot(ranksvf(),aes(Rank,input$parameterchoice,fill=Location))+
ggtitle("") +
theme(axis.title.y=element_blank())+
geom_bar(position="dodge",stat="identity")+
facet_wrap(~Tran.Hour.2h.Slot,nrow=2)
)
})
When I say it doesn't render a plot correctly, I mean two things:
1) When I use input$parameterchoice in ggplot, the graph comes out weird. It looks like this. Incorrect Plot
2) When I use the actual name of the input in ggplot instead of input$parameterchoice, the plot comes out fine. However when I mouseover the plot, the values do not show as they should (it is a plotly graph so it should show).
What I find strange is that I use a ggplotly in Tab 2 of my application as well, and it works fine (the mouseover works too).
I feel the problem has something to do with the way I used my reactive functions, though I'm not sure. I've tried to debug for a while, but no luck so far.
This is what my app looks like.
####
#UI#
####
ui=fluidPage(theme = shinytheme("paper"),
titlePanel("Visualising Site-Specific Indicators: XYZ University"),
#img(src='xyz.jpg', align = "left"),
tabsetPanel(
#TAB 1
tabPanel(type="pills","Macro-View of Locations",
fluidRow(
column(width = 4,
wellPanel(
selectInput("size",
label="Select Parameter for Rectangle Size",
choices=names(details)[2:5],selected = "Average Daily Transactions"))),
column(width = 4,
wellPanel(
selectInput("color",
label="Select Parameter for Rectangle Color",
choices=names(details)[2:5],selected = "Unique Products Sold"))
)#Close column
), #Close fluidRow
fluidRow(
plotOutput("plot")),
fluidRow(
dataTableOutput("tab"))
),#Close tabPanel macroview
#TAB 2
tabPanel("Transaction Overiew by Location",
fluidRow(
column(width = 4,
wellPanel(
selectInput("sitechoice",
label="Select a Site",
choices=unique(heatmap_mean$Location),selected = "Horton 1"))
)#Close column
), #Close fluidRow
fluidRow(
plotlyOutput("heatmap")),
fluidRow(
dataTableOutput("tab2"))
),#Close tabPanel transactionoverview
#TAB 3
tabPanel("Parameter Ranking",
fluidRow(
column(width = 4,
wellPanel(
selectInput("parameterchoice",
label="Rank By",
choices=unique(c(names(rankdf_avgtran),names(rankdf_ticket)))[3:4],selected = "Average Transaction Value (USD)"))
),#Close column
column(width=6,
wellPanel(
sliderInput("rankchoice",
label="Number of Ranks Desired",
min=1,
max=10,
value=5))
)#Close column
), #Close fluidRow
fluidRow(
plotlyOutput("facetmap")),
fluidRow(
dataTableOutput("tab3"))
)#Close tabPanel transactionoverview
) #Close tabsetpanel
) #Close UI
########
#SERVER#
########
server=function(input, output,session) {
# TAB 1
sortTable <- reactive({
details[do.call(order, -details[as.character(input$size)]),]
})
output$plot= renderPlot ({
treemap(details,
index=c("Site"),
vSize=input$size,
vColor=input$color,
title="XYZ University: Overview of Site Data",
fontsize.title = 20,
#sortID = paste("-",input$sort,sep=""),
type="value")
})
output$tab <- renderDataTable({
sortTable()
})
#TAB 2
test=reactive({
heatmap_mean %>% filter(Location==input$sitechoice)
})
output$heatmap=renderPlotly({
ggplotly(
ggplot(test(), aes(Day, `Time Slot`)) +
geom_tile(aes(fill = `Average Number of Transactions`),color = "white") +
scale_fill_gradient(low = "lightblue", high = "darkblue") +
ylab("") +
xlab("") +
theme(legend.title = element_text(size = 8),
panel.background = element_blank(),
legend.text = element_text(size = 8),
plot.title = element_text(size=18),
axis.title=element_text(size=22,face="bold"),
axis.text.x = element_text(angle = 90, hjust = 1)) +
labs(fill = ""))
})
output$tab2 <- renderDataTable({
test()
})
#TAB 3
ranks_pen <- reactive({
if(input$parameterchoice=="Average Number of Transactions")
{
showdata=rankdf_avgtran %>%
group_by(Tran.Hour.2h.Slot) %>%
top_n(n = input$rankchoice, wt = `Average Number of Transactions`) %>% #For each time slot, cut off top n values.
mutate(Rank = rank(-`Average Number of Transactions`, ties.method = "first")) #And rank for each of the 'n' sites for each time slot
return(showdata)
}
else
if(input$parameterchoice=="Average Transaction Value (USD)")
{
showdata=rankdf_ticket %>%
group_by(Tran.Hour.2h.Slot) %>%
top_n(n = input$rankchoice, wt = `Average Transaction Value (USD)`) %>% #For each time slot, cut off top 'n' values.
mutate(Rank = rank(-`Average Transaction Value (USD)`, ties.method = "first")) #And rank the 'n' sites for each time slot
return(showdata)
}
})
ranksvf<- reactive({
ranks_pen() %>%
group_by(Tran.Hour.2h.Slot) %>% #Group the columns
arrange(Rank) #Arrange rank from 1 to 'n'
})
output$facetmap=renderPlotly({
ggplotly(
ggplot(ranksvf(),aes(Rank,input$parameterchoice,fill=Location))+
ggtitle("") +
theme(axis.title.y=element_blank())+
geom_bar(position="dodge",stat="identity")+
facet_wrap(~Tran.Hour.2h.Slot,nrow=2)
)
})
output$tab3 <- renderDataTable({
ranksvf()
})
}#Close server
#RUN APP
shinyApp(ui,server)
input$parameterchoice returns a quoted string, however aes only accepts unquoted strings as arguments. Using aes_ instead should resolve the issue
output$facetmap=renderPlotly({
pc <- input$parameterchoice
ggplotly(
ggplot(ranksvf(),aes_(quote(Rank),as.name(pc),fill=quote(Location)))+
ggtitle("") +
theme(axis.title.y=element_blank())+
geom_bar(position="dodge",stat="identity")+
facet_wrap(~Tran.Hour.2h.Slot,nrow=2)
)
})
Try it:
selectInput("parameterchoice",
label="Rank By",
choices=as.list(unique(c(names(rankdf_avgtran),names(rankdf_ticket)))[3:4]),
selected = "Average Transaction Value (USD)")