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>
Related
I want to change chart type from e_line to e_bar based on a condition. What I tried to do was using some reactive expression or if else inside plot, but neither of them works. Any ideas how to tackle this?
So, I need to change dynamically e_line, I tried this:
newChartType <- reactive({
df = switch(
someCondition,
'1' = echarts4r::e_line(ColumnName2),
'2' = echarts4r::e_bar(ColumnName2)
)
})
output$plot <- echarts4r::renderEcharts4r({
dataChartStats() %>%
echarts4r::e_charts(ColumnName1) %>%
newChartType() %>%
echarts4r::e_legend(show = FALSE)
})
but it doesn't work. I'm interested in general rule on how to change dynamically building elements of plot code (can be ggplot as well etc, here I used echarts4r).
I couldn't find a way of obtaining the chart type directly from an input element, but here's one way of doing it:
library(shiny)
library(tidyverse)
ui <- fluidPage(
selectInput(
"type",
"Select a chart type:",
c("point", "line")),
plotOutput("plot")
)
server <- function(input, output) {
output$plot <- renderPlot({
if (input$type == "line") {
mtcars %>% ggplot() + geom_line(aes(x=mpg, y=disp))
} else {
mtcars %>% ggplot() + geom_point(aes(x=mpg, y=disp))
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
Next time, please provide a minimum working example.
EDIT in response to OP's request for a solution based on a button click:
library(shiny)
library(tidyverse)
ui <- fluidPage(
actionButton("go", "Click me!"),
textOutput("type"),
# selectInput(
# "type",
# "Select a chart type:",
# c("point", "line")),
plotOutput("plot")
)
server <- function(input, output) {
v <- reactiveValues(type="line")
observeEvent(input$go, {
if (v$type == "line") v$type <- "point"
else v$type <- "line"
})
output$type <- renderText({ v$type })
output$plot <- renderPlot({
if (v$type == "line") {
mtcars %>% ggplot() + geom_line(aes(x=mpg, y=disp))
} else {
mtcars %>% ggplot() + geom_point(aes(x=mpg, y=disp))
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
The ggplot just shows a vertical line of values that doesn't change when I try changing the x axis selection. The only thing on the x axis is the word "column" when I try to change the x axis, instead of the values of df$column according to what's selected.
df_variable <- df
df_colnames <- colnames(df)
xaxis_input <- selectInput(
inputId = "xaxis",
label = "Feature of Interest",
choices = df_colnames,
selected = df_colnames['default']
)
ui <- fluidPage(
titlePanel("DF"),
xaxis_input,
plotOutput(
outputId = "df_plot",
)
)
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes(x = input$xaxis, y = some_other_col))
return(plot)
})
}
input$xaxis is a string, so you cannot use it directly inside aes().
Try using aes_string() instead.
Note that some_other_col should also be a string.
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes_string(x = input$xaxis, y = "some_other_col"))
return(plot)
})
A full working example:
library(shiny)
library(ggplot2)
df <- iris
df_colnames <- colnames(df)
xaxis_input <- selectInput(
inputId = "xaxis",
label = "Feature of Interest",
choices = df_colnames
)
ui <- fluidPage(
titlePanel("DF"),
xaxis_input,
plotOutput(
outputId = "df_plot",
)
)
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes_string(x = input$xaxis, y = "Sepal.Width"))
return(plot)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Good day
I am trying to plot the means and 95% confidence intervals for my shiny webpage but I can't seem to get it right.
I would like output similar to this
I have tried two methods
Using geom_errorbar
Here I tried creating a summary table that calculates the 95% CI and then plotting from there.
My code follows
ui <- fluidPage(
titlePanel("questionnaire"),
sidebarLayout(
sidebarPanel(
selectInput("question", "Choose a question",
colnames(Data[,3:(ncol(Data)-1)]))
),
mainPanel(
plotOutput("meanCI")
)
)
)
server <- function(input, output) {
ci <- reactive({
groupwiseMean(input$question ~ Date,
data = Data,
conf = 0.95,
digits = 3)
})
output$meanCI <- renderPlot(
ggplot(ci, aes(x=Date, y=Mean)) +
geom_errorbar(aes(ymin=Trad.lower, ymax=Trad.upper), width=.1) +
geom_point()
)
}
shinyApp(ui = ui, server = server)
But it gives me this error,
data must be a data frame, or other object coercible by fortify(), not an S3 object with class reactiveExpr/reactive
Option 2 was to use plotmeans from the gplot package
ui <- fluidPage(
titlePanel("questionnaire"),
sidebarLayout(
sidebarPanel(
selectInput("question", "Choose a question",
colnames(Data[,3:(ncol(Data)-1)]))
),
mainPanel(
plotOutput("meanCI")
)
)
)
server <- function(input, output) {
output$meanCI <- renderPlot(
plotmeans(input$question~Data$Date, connect = FALSE)
)
}
shinyApp(ui = ui, server = server)
But it results is this error,
variable lengths differ (found for 'Data$Date')
Any help will be greatly appreciated!
library(shiny)
library(rcompanion)
library(ggplot2)
ui <- fluidPage(
titlePanel("questionnaire"),
sidebarLayout(
sidebarPanel(
selectInput("question", "Choose a question",
colnames(iris)[1:4])
),
mainPanel(
plotOutput("meanCI")
)
)
)
server <- function(input, output) {
ci <- reactive({
groupwiseMean(data = iris,
var = input[["question"]],
group = "Species",
conf = 0.95,
digits = 3)
})
output[["meanCI"]] <- renderPlot({
ggplot(ci(), aes(x=Species, y=Mean)) +
geom_errorbar(aes(ymin=Trad.lower, ymax=Trad.upper), width=.1) +
geom_point()
})
}
shinyApp(ui = ui, server = server)
Your main error is the missing parentheses in ggplot(ci(), ....... The other one is input$question ~ Date, which doesn't work because input$question is a character string.
I tried to calculate the average of pedal length (or width) within in each species and then plot it in bar graph using the shinny app. But the mean function in summarize keeps giving me issues.
library(datasets)
library(shiny)
library(dplyr)
library(ggplot2)
data("iris")
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Analyze Iris table"),
# Sidebar with a dropdown menu selection input for key meausre compoenent
sidebarLayout(
sidebarPanel(
selectInput("yInput", "Measuring element: ",
colnames(iris), selected = colnames(iris)[2]),
selectInput('xInput', 'Grouper: ',
colnames(iris), selected = colnames(iris)[5])
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("barPlot")
)
)
)
Define server logic required to draw a histogram
server <- function(input, output) {
by_xInput <- reactive({
iris %>%
group_by(input$xInput) %>%
summarize(n = length(input$xInput), mean_y = mean(input$yInput))
})
output$barPlot <- renderPlot({
# generate bins based on input$bins from ui.R
ggplot(data = by_xInput(), aes(x = input$xInput, y = mean_y)) +
geom_bar(stat = 'identity')
})
}
Run the application
shinyApp(ui = ui, server = server)
Here, it is a string element, so convert to symbol and evaluate (!!)
library(dplyr)
library(shiny)
library(ggplot2)
server <- function(input, output) {
by_xInput <- reactive({
iris %>%
group_by_at(input$xInput) %>%
# n() can replace the length
# convert string to symbol and evaluate (!!)
summarize(n = n(), mean_y = mean(!! rlang::sym(input$yInput)))
})
output$barPlot <- renderPlot({
# as the input is a string, use `aes_string`
ggplot(data = by_xInput(), aes_string(x = input$xInput, y = "mean_y")) +
geom_bar(stat = 'identity')
})
}
-testing
shinyApp(ui = ui, server = server)
-output
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)
})