I'm having trouble with the server.R getting shiny to plot the data based on drop down selections from the ui.R. I would like to select a 'Site' and a 'Parameter' and plot the 'Obs' that reflects that 'Site' and 'Parameter'. Obs as the Y and Date on the X. Here is some sample code.
Site_Names=data.frame(c(A=rep("A",10),B=rep("B",10),C=rep("C",10)))
Site_Names=Site_Names[,1]
Parameters=data.frame(c(pH=rep("pH",10),DO=rep("DO",10),Temp=rep("Temp",10)))
Parameters=Parameters[,1]
Obs=rnorm(30)
Dates=c(seq(as.Date("2000/1/1"), by = "year", length.out =10 ),
seq(as.Date("2005/1/1"), by = "year", length.out =10 ),
seq(as.Date("1990/1/1"), by = "year", length.out =10 ))
data=data.frame(Site_Names,Parameters,Obs,Dates)
#ui.R
Sites=levels(data$Site_Name)
setNames(as.list(Sites), Sites)
params=levels(data$Parameters)
setNames(as.list(params), params)
library(shiny)
library(ggplot2)
shinyUI(fluidPage(
# Application title
titlePanel("Data"),
sidebarLayout(
sidebarPanel(
selectInput("site", "Select Site:", Sites),
selectInput("parameters", "parameter", params)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("Plot")
)
)
))
#server.R
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
dataset <- reactive({
data[ , (input$Sites),]
})
output$distPlot <- renderPlot({
p <- ggplot(dataset(), aes(x=Dates, y=input$params and input$Sites))
+ geom_point(data$Obs)
print(p)
})
You can use subset within your reactive expression to get the plot data. Be careful though, as you can end up with null values if the parameter isn't included in the site data.
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
dataset <- reactive({
subset(data, Site_Names == input$Sites & Parameters == input$params)
})
output$distPlot <- renderPlot({
p <- ggplot(dataset(), aes(x = Dates, y = Obs)) +
geom_line()
print(p)
})
Related
Given a shiny application with a ggplot2 plot, how would you update which x & y variable are used to construct the plot based on user input?
Code:
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("xcol",
"X:",
choices = c("Sepal.Length", "Sepal.Width")
),
selectInput("ycol",
"Y:",
choices = c("Sepal.Length", "Sepal.Width")
)
),
mainPanel(plotOutput("plot"))
)
)
server <- function(input,output) {
output$plot <- renderPlot({
iris %>%
ggplot(aes(input$xcol, input$ycol)) +
geom_point()
})
}
shinyApp(ui, server)
Desired output:
Current output:
You are trying to map aesthetics with character vectors in the aes function. You need aes_string instead:
###<Omitted Library Calls and UI>
server <- function(input,output) {
output$plot <- renderPlot({
iris %>%
ggplot(aes_string(x= input$xcol, y = input$ycol)) +
geom_point()
})
}
###<Omitted shinyApp call>
In Shiny, I want to create a reactive object, a dataframe, that updates a plot automatically when values in that object change. I am aware that one needs to use parentheses for that object in subsequent usage. For some reason, I am still getting the error "object of type 'closure' is not subsettable".
I have tried to reactive(), reactiveValues() and reactiveVal(), but none produce the desired result. Any ideas?
require(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
df <- reactive({
relevant.values <- input$y.value
df <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
df
})
output$plot <- renderPlot({
mydata <- df()
# relevant.values <- input$y.value
# data <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
ggplot(mydata, aes(x = hp , y = mpg )) + geom_line()
})
}
shinyApp(ui, server)
I think that there are two problems with your code:
You can't create a reactive expression called df which modifies an object called df, i.e. the same as the expression;
The code which(df$mpg %in% relevant.values[1]:relevant.values[2]) does not filter the values of mpg between relevant.values[1] and relevant.values[2] but it selects the values of mpg which are exactly equal to relevant.values[1]:relevant.values[2].
I modified your script as follows:
library(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(
inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y - 1, mean.y + 1),
step = 0.5
)
),
mainPanel(
plotOutput("plot")
)
)
))
server <- function(input, output) {
filtered_df <- reactive({
df[which(df$mpg >= input$y.value[1] & df$mpg <= input$y.value[2]), ]
})
output$plot <- renderPlot({
ggplot(filtered_df(), aes(x = hp, y = mpg)) + geom_line()
})
}
shinyApp(ui, server)
The error is primarily because you have an object called df which is a copy of mtcars as well as a reactive object called df.
Renaming your reactive is the easier fix:
require(ggplot2)
library(shiny)
# data pre-processing
# loading data from local machine
data(mtcars)
df <- mtcars
# processe
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
dfr <- reactive({
relevant.values <- input$y.value
df <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
df
})
output$plot <- renderPlot({
mydata <- dfr()
# relevant.values <- input$y.value
# data <- df[which(df$mpg %in% relevant.values[1]:relevant.values[2]),]
ggplot(mydata, aes(x = hp , y = mpg )) + geom_line()
})
}
shinyApp(ui, server)
I did it like this, please try it and tell me if is ok.
require(ggplot2)
library(shiny)
data(mtcars)
df <- mtcars
min.y <- min(df$mpg)
max.y <- max(df$mpg)
mean.y <- mean(df$mpg)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "y.value",
label = "Filter mpg",
min = min.y,
max = max.y,
value = c(mean.y-1, mean.y+1),
step = 0.5)
),
mainPanel(
plotOutput("plot")
))))
server <- function(input, output) {
output$plot<- renderPlot({
output$plot <- renderPlot({
a=input$y.value[1] ; b=input$y.value[2]
hp_reac <- df$hp[a:b]
mpg_reac <- df$mpg[a:b]
ggplot(df[a:b,], aes(x = hp_reac , y = mpg_reac )) + geom_line()
})
})
}
shinyApp(ui, server)
I am getting an error with the plotting index using plotly in conjunction with reactive values in shiny. The sidebar panel loads with no issues but there is a problem displaying the chart that I cannot determine. Any help solving the index problem would be much appreciated. Thanks!
library(shiny)
library(plotly)
data(economics, package = "ggplot2")
nms <- names(economics)
ui <- fluidPage(
headerPanel("TEST"),
sidebarPanel(
selectInput('x', 'X', choices = nms, selected = nms[[1]]),
selectInput('y', 'Y', choices = nms, selected = nms[[2]]),
sliderInput('plotHeight', 'Height of plot (in pixels)',
min = 100, max = 2000, value = 1000)
),
mainPanel(
plotlyOutput('trendPlot', height = "900px")
)
)
server <- function(input, output) {
#add reactive data information. Dataset = built in diamonds data
dataset <- reactive({economics[, c(input$xcol, input$ycol)]
})
output$trendPlot <- renderPlotly({
# build graph with ggplot syntax
p <- ggplot(dataset(), aes_string(x = input$x, y = input$y)) +
geom_line()
ggplotly(p) %>%
layout(height = input$plotHeight, autosize=TRUE)
})
}
shinyApp(ui, server)
Warning: Error in : Unsupported index type: NULL
You have mistakenly used xcol and ycol not sure why. Without those names the code works fine.
library(shiny)
library(plotly)
library(tidyverse)
data(economics, package = "ggplot2")
nms <- names(economics)
ui <- fluidPage(
headerPanel("TEST"),
sidebarPanel(
selectInput('x', 'X', choices = nms, selected = nms[[1]]),
selectInput('y', 'Y', choices = nms, selected = nms[[2]]),
sliderInput('plotHeight', 'Height of plot (in pixels)',
min = 100, max = 2000, value = 1000)
),
mainPanel(
plotlyOutput('trendPlot', height = "900px")
)
)
server <- function(input, output) {
#add reactive data information. Dataset = built in diamonds data
dataset <- reactive({
economics[, c(input$x, input$y)]
})
output$trendPlot <- renderPlotly({
# build graph with ggplot syntax
p <- ggplot(dataset(), aes_string(input$x, input$y)) +
geom_line()
ggplotly(p, height = input$plotHeight)
})
}
shinyApp(ui, server)
I built the shiny app below that updates the line graph based on the user's input. It works fine until I try to generate a 2nd output. How can I display the value total.weight calculated in the renderPlot() function? It seems to me my data set df and the variable total.weight should be created "outside" of the renderPlot() function but I have not figured out how.
ui.r
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Reproducible Example"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput("ID", "group", c("A", "B"))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("plot1"),
verbatimTextOutput("text1")
)
)
))
server.r
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
total.weight <- sum(df$weight)
#Plot
ggplot(data=df, aes(x=df$years, y=df$weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight})
})
Output snapshot:
You can also create reactives:
server.R
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
df <- reactive({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
})
total.weight <- reactive({
sum(df()$weight)
})
output$plot1 <- renderPlot({
#Plot
ggplot(data=df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight()})
})
The quick workaround is to put the total weight in a global varaiable:
total.weight <<- sum(df$weight)
The nice way to do it is to subset your data.frame within a reactive function:
shinyServer(function(input, output) {
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
reactive_df <- reactive(subset(df, group == input$ID))
output$plot1 <- renderPlot({
ggplot(data=reactive_df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({sum(reactive_df()$weight)})
})
I am a little confused about printing the dynamic output while using R in shiny. The following are my code in shiny, it can just print out the ggplot2 charts, but not along with the new data frame. I just wanna know how to print out "mydata" at the same time. Thanks.
library("reshape2")
library("ggplot2")
Server.R
shinyServer(function(input, output) {
output$main_plot <- renderPlot({
#Draw gragh to compare the forecast values with real data
mydata <- data.frame(years, A, B)
df <- melt(mydata, id = 'years', variable = 'series')
print(ggplot(df, aes(years,value)) + geom_line(aes(colour = series), size=1.5))
})
Ui.R
shinyUI(pageWithSidebar(
# Sidebar with controls to select a dataset
# of observations to view
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("Netflix"))),
plotOutput(outputId = "main_plot", height = "500px")
))
Pull out the data frame into a reactive expression, so you can use it from two different outputs. (This is the reactive analog to introducing and reusing a variable.)
server.R
shinyServer(function(input, output) {
mydata <- reactive({
data.frame(years, A, B)
})
output$main_plot <- renderPlot({
#Draw gragh to compare the forecast values with real data
df <- melt(mydata(), id = 'years', variable = 'series')
print(ggplot(df, aes(years,value)) + geom_line(aes(colour = series), size=1.5))
})
output$data <- renderTable({ mydata() })
})
ui.R
shinyUI(pageWithSidebar(
# Sidebar with controls to select a dataset
# of observations to view
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("Netflix"))),
plotOutput(outputId = "main_plot", height = "500px"),
tableOutput(outputId = "data")
))