I have a dataset with home values for all 50 states over ~30 years. Columns include State, Year, Value, etc. I am trying to create an interactive Shiny app where the user can select certain states so they will be the only ones displayed in the plot. I have successfully created the plot of all states independently where Year is on the x-axis and Value is on the y-axis, colored by State, and also have successfully subset the dataset so that only one state plots.
I am new to Shiny and having issues having anything other than the Input checkBox feature work in this. Is there something obvious I am missing?
ui <- fluidPage(
checkboxGroupInput(inputId = "state", label = "States", choices = levels(AllData2$STATE),
plotOutput(outputId = "hist")))
server <- function(input, output) {
output$hist <- renderPlot({
plot(data = subset(AllData2, AllData2 == input$state), mapping = aes(x = Date, y = HomeValue,
color = STATE) + geom_line(size=2, alpha=0.8) +
scale_y_continuous(breaks = seq(0, 1000000, 50000)) +
scale_x_continuous(breaks = seq(1975, 2020, 5)) +
ylab("Value in Dollars") + xlab("Year"))
})
}
shinyApp(ui = ui, server = server)
I get no output in my Shiny App except the checkbox options. Thank you for any help.
There are only syntax errors in your code. Many of them:
You have included plotOutput() inside the checkbox group, please place it outside it.
Use ggplot() instead of plot()
You have included everything inside plot() If you use ggplot() the syntax is: ggplot(data=AllData,mapping=aes())+geom_line()+scale_y_continuous()+scale_x_continuous()+labs(x="This is X label",y="This is ylab",color="This is the color legend label")
Your code will work after fixing these problems
Just copy paste this if you want instant result:
library(shiny)
library(ggplot2)
library(dplyr)
ui <- fluidPage(
column(12,checkboxGroupInput(inputId = "state", label = "States", choices = c(1,2,3,4,5))),
column(12,plotOutput(outputId = "hist")))
server <- function(input, output) {
output$hist <- renderPlot({
ggplot(data = subset(AllData2, AllData2$STATE %in% input$state), mapping = aes(x = Date, y = HomeValue,
color = STATE)) + geom_line(size=2, alpha=0.8) +
scale_y_continuous(breaks = seq(0, 1000000, 50000)) +
scale_x_continuous(breaks = seq(1975, 2020, 5)) +labs(x="Value in Dollars",y="Year")
})
}
shinyApp(ui = ui, server = server)
Related
I am learning how to use Shiny, and I tried to create a very simple barchart in ggplot2, with a dropdown menu, that allows the user to select a class from a school using the dropdown, and it is supposed to create a barchart with exam result percentages on the y-axis and names on the x-axis. The code I have is as follows:
ui = fluidPage(selectInput(inputId = "Class", label = "Pick a Class", choices = levels(fulldata$Class), plotOutput("bar"), multiple = FALSE, selectize = FALSE))
server = function(input, output){
output$bar = renderPlot({
plotdata = reactive({data %>% filter(Class == input$Class)})
ggplot(plotdata(), aes(x = Name, y = Percent_full) + geom_bar())
})
}
shinyApp(ui = ui, server = server)
The end result correctly renders the dropdown menu, but it does not render the plot whatsoever. I have tried changing the ggplot call to a simple hist(rnorm(1000)) but it does not render either.
I solved the problem: the plotOutput function in the fluidPage function was defined as an argument of the input function, not as an argument of fluidPage. It works now!
It might be that your code needs to declare the reactive data before you create your ggplot.
Try this:
plotdata = reactive(
data %>% filter(Class == input$Class)
)
output$bar = renderPlot({
ggplot(plotdata(), aes(x = Name, y = Percent_full) + geom_bar())
})
Here is more example code from a functioning shiny app using reactive data for ggplot:
data <- reactive(
merged_clean_data %>% filter(between(date, as.POSIXct(input$dateRange[1]),
as.POSIXct(input$dateRange[2])))
)
#Output plot for any selected variable
output$timePlot <- renderPlot({
ggplot(data(), aes(x = date, !!input$selection)) +
theme_classic() + geom_line() +
coord_cartesian(xlim = as.POSIXct(ranges$x, origin = "1970-01-01"), expand = FALSE) +
theme(text = element_text(size = 16), axis.title.x=element_blank(), axis.text.y = element_text(angle=90, vjust=1, hjust=1)) + {if(input$hlineadd)geom_hline(yintercept = input$hline)} +
{if(input$smoothingadd)geom_smooth()}
}, res = 80)
I want to build a shiny app using Covid-19 data (https://data.europa.eu/euodp/de/data/dataset/covid-19-coronavirus-data) and I would like to show barplot with ggplot where you can see the development of worldwide cases or deaths over time. I would furthermore like to have a dateRangeInput in which you can set a time period. At the same time I have on the y axis either the possibility to choose from selectInput either the variable "cases" or "deaths". I can do this separately but I can't figure out how to have this in one final plot.
It works with the time range if I use this code:
ui <- fluidPage(
titlePanel("Covid-19 by Country"),
sidebarLayout(
sidebarPanel(
selectInput(inputId = "y", label = "Y-Axe:",
choices=c("cases", "deaths"),
selected = "cases"),
dateRangeInput("datum", "Zeitraum auswählen", start = min(covid_worldwide$dateRep), end = max(covid_worldwide$dateRep), min = min(covid_worldwide$dateRep), max = max(covid_worldwide$dateRep), format = "dd.mm.yyyy", language = "de")
),
mainPanel(
plotOutput("covidPlot")
)
)
)
server <- function(input, output, session) {
s <- reactive({
covid_worldwide %>%
filter(
as.Date(dateRep) >= as.Date(input$datum[1]),
as.Date(dateRep) <= as.Date(input$datum[2])
)
})
output$covidPlot <- renderPlot({
ggplot(data= s(), aes(x = dateRep, y = cases)) +
geom_bar(stat="identity", fill="red") + theme_classic() + xlab("Zeitraum") + ylab("Anzahl")
}
)}
shinyApp(ui = ui, server = server)
It works also if I do not change the time period but give two different variables for the y-axis, see following code (the UI is the same as above):
server <- function(input, output, session) {
s <- reactive({
covid_worldwide %>%
filter(
as.Date(dateRep) >= as.Date(input$datum[1]),
as.Date(dateRep) <= as.Date(input$datum[2])
)
})
yvar <- reactive({
if ( "cases" %in% input$y) return(covid_worldwide$cases)
if ( "deaths" %in% input$y) return(covid_worldwide$deaths)
})
output$covidPlot <- renderPlot({
ggplot(data= s(), aes(x = dateRep, y = yvar())) +
geom_bar(stat="identity", fill="red") + theme_classic() + xlab("Zeitraum") + ylab("Anzahl")
}
)}
shinyApp(ui = ui, server = server)
But if I then try to change the time period in the shiny app I receive this error: "Aesthetics must be either length 1 or the same as the data (26852): y"
Does anyone have an idea on how to make the two things in one ggplot barplot work? Thank you in advance!
You simply have to map input$y on y in your plotting code. Additionally as the input is a character it's convenient to switch to aes_string instead of aes as it allows to pass the variables as names or strings to ggplot().
The first version does not work as you map cases on y. The second one does not work as your reactive yvar extracts a vector from the original unfiltered df. Therefore the length of yvar is greater than the number of rows of the filtered df or the length of your date variable.
output$covidPlot <- renderPlot({
ggplot(data= s(), aes_string(x = "dateRep", y = input$y)) +
geom_bar(stat="identity", fill="red") + theme_classic() + xlab("Zeitraum") + ylab("Anzahl")
}
My file is one set of game data and PitchNo tells the pitch of the game. I am trying to generate plots of each batter's pitches seen in a game and I have labeled the PitchNo in the ggplot function. I want my plot for each batter to label the pitches seen, say 1-10, but instead it is still labeling them as the PitchNo of the game.
I added Batter$PitchNo <- 1:nrow(Batter) in my reactive filter. That line of code works in normal R but I cannot seem to find a way to make in work in a Shiny app.
library(shiny)
library(tidyverse)
GameDataFile <- read_csv("GameDataFile.csv")
GameDataFile %>% group_by(PitchNo)
playerlist <- sort(unique(GameDataFile$Batter))
ui = fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
selectInput(
inputId="Batter1",
label="Player:",
choices = playerlist)
),
mainPanel(
plotOutput("myZone")
)))
server = function(input, output){
output$myZone <- renderPlot({
GameDataFile$PlateLocSide <- (GameDataFile$PlateLocSide * -1)
newdata <- reactive({
GameDataFile %>% filter(
Batter %in% c(input$Batter1),
Batter$PitchNo <- 1:nrow(Batter)) # Error is here
})
ggplot(data = newdata(), aes(x = PlateLocSide, y = PlateLocHeight)) +
xlim(-2.5,2.5) + ylim(0,5) + scale_fill_viridis_c() + geom_point() +
labs(x = "", y = "") + facet_wrap(~ Batter, ncol = 2) +
geom_text(aes(label = PitchNo), vjust = -0.5) + theme_bw() +
theme(strip.text = element_text(size=20, face="bold"))
}, width=400, height=500)
}
shinyApp(ui = ui, server = server)
I have tried many data structure permutations to try to get the data updating in the plot (e.g., subset, preset matrices)
names(datar):
"Sex" "Age" "Year" "PercViewing.DIVORCED" "PercViewing.MARRIED" "PercViewing.NEVER MARRIED"
The desired plot is generated when run alone with input$select identified. However, input$select appears not to be passed from ui to the server script as written (below).
ui.r
library(shiny)
shinyUI(
fluidPage(
headerPanel("Have you seen an X-rated movie\nin the last year?"),
sidebarLayout(
sidebarPanel(selectInput("select","Select marital status to view",paste(choices=names(datar[4:6])))),
mainPanel(img(src="liberos.jpg", height = 200, width = 200),h2("Title here",align = "center"),plotOutput("densPlot"))
)
)
)
server.r
library(shiny)
library(ggplot2)
data<-read.table("/Users/nicole/Dropbox/Shiny/xmoviePerc.csv", sep=",",stringsAsFactors =FALSE
shinyServer(function(input, output){
output$densPlot <- renderPlot({
ggplot(datar, aes(x=input$select,fill=datar$Sex)) +
geom_density(alpha = 0.5,colour=c("yellow")) +
labs(title = "Percent who reported viewing\nsex films") +
ylab("Response density") +
xlab("Percent who report having viewed") +
theme(axis.title = element_text(family="Times", face="bold",colour="darkred", size=rel(1.3))) +
geom_text(data = NULL, x = 20, y = .015, label = input$select,aes(label=text,family="Times")) +
scale_fill_discrete(name="Gender reported") +
theme(legend.title = element_text(colour="black", size=16, face="bold"))
})
})
Try using aes_string() instead in your ggplot() call in server.r. aes() uses non-standard evaluation, and so it can't understand the text string that input$select evaluates to.
Just discovering shiny apps but this is driving me insane.......I have looked at numerous examples of server.R and ui.R code and cannot figure out what I am doing wrong. Apologies in advance if it's something very basic..........
Taking the iris dataset as an example, I want to plot one column against another, something simple using qplot or preferably ggplot
However, using qplot I get this:
and using ggplot2, I get the error:
I don't think I need the reactive function as I'm not subsetting the dataset, just extracting columns to plot.
server.R code
library(shiny)
library(shinyapps)
library(ggplot2)
shinyServer(function(input, output, session) {
output$text1 <- renderText({input$id1})
output$text2 <- renderText({input$select1})
output$plot1 <- renderPlot({
g <- qplot(Sepal.Length, input$select1, data = iris)
print(g)
})
})
or using ggplot function to replace the qplot call
g <- ggplot(iris, aes(x = Sepal.Length, y = input$select1))
g <- g + geom_line(col = "green", lwd =1) +
labs(x = "Date", y = "Ranking") +
theme_bw() + scale_y_reverse()
ui.R code
library(shiny)
library(shinyapps)
data(iris)
opts <- unique(colnames(iris))
opts <- opts[-1] ## want to keep Sepal.Length as the x values
shinyUI(pageWithSidebar(
headerPanel('test with iris database'),
sidebarPanel(
selectInput(inputId = "select1", label = "select",
choices = opts),
textInput(inputId = "id1", label = "Input Text", "")
),
mainPanel(
p('Output text1'),
textOutput('text1'),
textOutput('text2'),
plotOutput('plot1')
)
))
Change your aes statement to aes_string and make x a string. This should fix the problem.
g <- ggplot(iris, aes_string(x = "Sepal.Length", y = input$select1))
g <- g + geom_line(col = "green", lwd =1) +
labs(x = "Date", y = "Ranking") +
theme_bw() + scale_y_reverse()