I want to start a shiny app for practice where a use can choose from a dropdown the values in the "cut" column from the diamonds dataset (from ggplot2).
My ui looks as following:
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Reactive Boxplot"),
# Show a boxplot of the selected cut
mainPanel(
selectInput("column", label = h3("Column to plot"),
choices = c("", diamonds$cut),
selected = 1,
width='55%',
multiple = FALSE),
plotOutput("diamondshist")
)
)
)
I don't know how to define the input variables as the five distinct values in the "cut" column of diamonds dataset. Any input on this?
My server file looks like shared below. I assume I would also need to adapt the input data for the plot.
library(shiny)
library(ggplot2)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
compute_plot <- reactive({
if (input$column != ""){
ggplot(diamonds[, input$column])+
labs(title = "From diamonds dataset")+
geom_boxplot(aes(x = cut, y = price))+
scale_y_reverse()
}
})
output$diamondshist <- renderPlot({
compute_plot();
})
})
I assume this is what you are after:
pass the levels of diamonds$cut as input selection
subset the diamonds dataset to the selected cut
library(shiny)
library(ggplot2)
# Define UI for application that draws a histogram
ui=shinyUI(fluidPage(
# Application title
titlePanel("Reactive Boxplot"),
# Show a boxplot of the selected cut
mainPanel(
selectInput("column", label = h3("Column to plot"),
choices = c("", levels(diamonds$cut)),
selected = NULL,
width='55%',
multiple = FALSE),
plotOutput("diamondshist")
)
)
)
# Define server logic required to draw a histogram
server=shinyServer(function(input, output) {
compute_plot <- reactive({
if (input$column != ""){
ggplot(subset(diamonds, cut==input$column))+
labs(title = "From diamonds dataset")+
geom_boxplot(aes(x = cut, y = price))+
scale_y_reverse()
}
})
output$diamondshist <- renderPlot({
compute_plot();
})
})
shinyApp(ui = ui, server = server)
Related
Not sure why my code shows all the countries' plots at the same time, I want to make it display only the country that's selected by the user. Does anyone know what went wrong with the code?
library(shiny)
require(readr)
countries <- read.csv("~/Desktop/share-deaths-suicide.csv")
# Define UI for application that draws a scatterplot
ui <- fluidPage(
# Application title
titlePanel("Country Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Entity",
"countries",
paste(countries$Entity),
selected = "China", multiple = FALSE)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("countryPlot")
)
)
)
# Define server logic required to draw a scatterplot
server <- function(input, output) {
output$countryPlot <- renderPlot({
country = input$Entity
plot(countries$Year, countries$`Deaths...Self.harm...Sex..Both...Age..All.Ages..Percent`, col=ifelse(countries$Entity==country, "red","black"),
main = "Sucide Rate of Countries", xlab = "Year", ylab = "Sucide rate",log="xy")
options(scipen=999)
})
}
# Run the application
shinyApp(ui = ui, server = server)
The issue is that you do not filter your data for the selected country. According to your code only the color is changed for the selected country.
To fix you issue you have to filter your data before passing it to plot. To this end you could add a reactive which filters the data. The filtered data could then be used via countries_filtered() where the parantheses are important. Additionally I have fixed an issue with your selectInput. Instead of passing the vector of entities use only the unique values for the choices argument.
As you provided no example data (to this end I would suggest to have a look at how to provide provide a minimal reproducible example) I use the gapminder dataset as example data:
library(shiny)
# Example data
library(gapminder)
countries <- gapminder
names(countries)[c(1, 3, 4)] <- c("Entity", "Year", "Deaths...Self.harm...Sex..Both...Age..All.Ages..Percent")
# Define UI for application that draws a scatterplot
ui <- fluidPage(
# Application title
titlePanel("Country Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Entity",
"countries",
choices = unique(countries$Entity),
selected = "China", multiple = FALSE)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("countryPlot")
)
)
)
# Define server logic required to draw a scatterplot
server <- function(input, output) {
countries_filtered <- reactive({
req(input$Entity)
countries[countries$Entity == input$Entity, ]
})
output$countryPlot <- renderPlot({
country = input$Entity
plot(countries_filtered()$Year, countries_filtered()$`Deaths...Self.harm...Sex..Both...Age..All.Ages..Percent`,
col=ifelse(countries$Entity==country, "red","black"),
main = "Sucide Rate of Countries", xlab = "Year", ylab = "Sucide rate",log="xy")
options(scipen=999)
})
}
# Run the application
shinyApp(ui = ui, server = server)
#>
#> Listening on http://127.0.0.1:4061
1: You need to filter the dataset for the input country
And I will demonstrate this using ggplot:
output$countryPlot <- renderPlot({
countries %>%
filter(country == input$Entity) %>%
plot(aes(Year, countries$`Deaths...Self.harm...Sex..Both...Age..All.Ages..Percent`, color= Entity)) +
geom_point() +
labs(main = paste("Sucide Rate of", input$Entity), xlab = "Year", ylab = "Sucide rate") +
scale_y_log10() +
scale_x_log10() +
scale_fill_manual(values=c("red", "black"))
options(scipen=999)
})
I am not exactly sure why you wanted to color the points of the scatter plot based on "entity" as it seems that entity is the country input and the original plot would change the color of the points based on the user selection. In my above code, it would change the entire plot to only show the selected country, and changes the title based on the country selected as well.
So, I need to make a shiny app that takes a dynamic number of inputs to eventually do dimension reduction, but I'm stuck trying to figure out how to refer to what's in my inputs when I have a dynamic number of them. I'm using the iris dataset and the inputs are the variables. Part of what I need to do is plot 2 of them with a k means, but I'm just trying to 1st make a basic plot. What I have so far is
library(shiny)
library(ggplot2)
ui <- shinyUI(fluidPage(
titlePanel("Old Faithful Geyser Data"),
fluidRow(
column(2,
textInput(inputId = "number", label = "number of selectInput",value = 2)
),
column(8,
plotOutput("distPlot")),
column(2,
uiOutput(outputId = "putselect"))
)
))
server <- shinyServer(function(input, output) {
output$putselect = renderUI(
if(input$number != 0 ){
lapply(1:(input$number), function(i){
selectInput(inputId = paste0("var",i), label = paste0("input ",i), choices = names(iris))
})
}
)
output$distPlot <- renderPlot({
ggplot(iris, aes(x = input$var1, y = input$var2, color = Species)) +
geom_point()
})
})
shinyApp(ui = ui, server = server)
In my output$distplot what goes in the ggplot x and y? The way I have it now it shows up and the labels on the graph change, but there are no points on the graph. I'm new to using Shiny so any help would be appreciated.
instead of aes use aes_string like:
ggplot(iris, aes_string(x = input$var1,
y = input$var2,
color = "Species"
)
)
note to quote the variables supplied as a string (Species in this case)
see: Shiny: passing input$var to aes() in ggplot2
I am trying to make a shiny app that will allow to color the points of the scatterplot based on the selected categorical variables.
library(shiny)
data<-data.frame(iris)
ui <- navbarPage("Summary",
tabsetPanel(
tabPanel("Graph", fluid=T,
fluidPage(
sidebarPanel(selectInput(inputId = "varColor",
label = "Color",
choices = c("Species", "Other_Category"),
selected = "Species")),
mainPanel(plotOutput(outputId = "plot"))
)
)
)
)
server <- function(input, output) {
p<-reactive({ggplot(data,
aes(y = Sepal.Length, x = Petal.Length))+
# This Part needs help
geom_point(aes( input$varColor)) })
output$plot <- renderPlot({
p()
})
}
shinyApp(ui, server)
I think that now, the program reads the color selection from the input as a string, instead of taking it as category.
Thank you for help.
The issue is that input$colorVar is simply a character. Hence, ggplot2 will treat this character value as the one and only category. Hence, you end up with one color.
To tell ggplot2 that it should color the plot according to the data column whose named is stored in input$colorVar you could make use of the so called .data pronoun provided by the rlang package, i.e. do aes(color = .data[[input$varColor]]):
library(shiny)
library(ggplot2)
data <- data.frame(iris)
ui <- navbarPage(
"Summary",
tabsetPanel(
tabPanel("Graph",
fluid = T,
fluidPage(
sidebarPanel(selectInput(
inputId = "varColor",
label = "Color",
choices = c("Species", "Other_Category"),
selected = "Species"
)),
mainPanel(plotOutput(outputId = "plot"))
)
)
)
)
#> Warning: Navigation containers expect a collection of `bslib::nav()`/
#> `shiny::tabPanel()`s and/or `bslib::nav_menu()`/`shiny::navbarMenu()`s. Consider
#> using `header` or `footer` if you wish to place content above (or below) every
#> panel's contents.
server <- function(input, output) {
p <- reactive({
ggplot(
data,
aes(y = Sepal.Length, x = Petal.Length)
) +
# This Part needs help
geom_point(aes(color = .data[[input$varColor]]))
})
output$plot <- renderPlot({
p()
})
}
shinyApp(ui, server)
#>
#> Listening on http://127.0.0.1:3070
I have created a shiny app should take input from three sliders and:
Plots a distribution in ggplot
Show a summary table of values underneath the plot in #1 above
If I just want to plot the histogram (and I comment out the table data), I can get the code to work correctly. However, when I add the table, the plot disappears even though the plot header is still there. I have tried moving the commas a braces around to see if it's a simple syntax error but haven't had any luck.
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Test Shiny Layout"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
h4("Input Data"),
sliderInput("bins", "Bin Width", min = 4,max = 12, value = 8),
),
# Show a plot of the generated distribution
mainPanel(
h4("Histogram"),
plotOutput("distPlot", width = "600", height = "600"),
h4("Table of Values"),
tableOutput("table")
)
)
))
Server
library(shiny)
library(ggplot2)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
bins <- input$bins
df1 <- (iris$Sepal.Length)
x <- mean(df1)
y <- sd(df1)
ggplot(data = iris) +
geom_histogram(mapping = aes(x = Sepal.Length), color = "blue", binwidth = "bins")
# Create an empty dataframe and then plug in the mean and standard deviation
results <- data.frame("0", "0")
results[1,1] = x
results[1,2] = y
colnames(results) <- c("Mean", "SD")
rownames(results) <- c("Sepal Length")
output$table <- renderTable(results)
})
})
Your renderTable() is inside your renderPlot() call. So renderPlot isn't returning anything.
You were right: it was a simple syntax error. But you also had several other issues in your code. At least a dozen. Three in binwidth = "bins" alone.
Here's a working version. I suspect you will still want to make tweaks, but at least you have both a histogram and a summary table that both look reasonably sensible.
library(shiny)
library(ggplot2)
data(iris)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
ggplot(data = iris) +
geom_histogram(aes(x = Sepal.Length), color = "blue", bins = input$bins)
})
output$table <- renderTable({
iris %>%
summarise(Mean=mean(Sepal.Length),
SD=sd(Sepal.Length))
})
}
ui <- fluidPage(
titlePanel("Test Shiny Layout"),
sidebarLayout(
sidebarPanel(
h4("Input Data"),
sliderInput("bins", "Bin Width", min = 4,max = 12, value = 8),
),
mainPanel(
h4("Histogram"),
plotOutput("distPlot", width = "600", height = "600"),
h4("Table of Values"),
tableOutput("table")
)
)
)
shinyApp(ui = ui, server = server)
I am working on a shiny app where I allow a user to select the plotting criteria and then also allow them to brush the plot and see their selection in a table below. I have some NA values in my data. I have noticed that these NAs end up in my brushed point table as full rows of NA. I can remove these manually with something like this. However, I was wondering if I perhaps was doing something wrong on my brush that was causing this.
Code with a working example is below. I have also included an image of a brush selection demonstrating what I mean.
library(shiny)
library(tidyverse)
# replace some random values in mtcars with NA
set.seed(1)
mtnew <-
as.data.frame(lapply(mtcars, function(m)
m[sample(
c(TRUE, NA),
prob = c(0.8, 0.2),
size = length(m),
replace = TRUE
)]))
# set up UI that allows user to pick x and y variables, see a plot,
# brush the plot, and see a table based on the brush
ui <- fluidPage(
titlePanel("Shiny Test"),
sidebarLayout(
sidebarPanel(
selectInput("xvar",
"pick x",
choices = names(mtnew)),
selectInput("yvar",
"pick y",
choices = names(mtnew))),
mainPanel(
plotOutput("myplot",
brush = brushOpts(id = "plot_brush")),
tableOutput("mytable")
)
)
)
server <- function(input, output) {
output$myplot <- renderPlot({
ggplot(data = mtnew) +
geom_point(aes(x = !!rlang::sym(input$xvar),
y = !!rlang::sym(input$yvar)))
})
output$mytable <- renderTable({
brush_out <- brushedPoints(mtnew, input$plot_brush)
})
}
# Complete app with UI and server components
shinyApp(ui, server)
I guess that you'll have to establish which data you want to represent.
You may want to have only defined record without NAs, in that case I would suggest to use the complete.cases function. Yet this solution will highly reduce your data set (below I've applied to your code).
Another option is to preserve all your records but without the NAs. In that case you should consider using imputation methods to set proper values in replacement. Take a look at this post which provides an example.
library(shiny)
library(tidyverse)
# replace some random values in mtcars with NA
set.seed(1)
mtnew <-
as.data.frame(lapply(mtcars, function(m)
m[sample(
c(TRUE, NA),
prob = c(0.8, 0.2),
size = length(m),
replace = TRUE
)]))
mtnew_complete <- mtnew[complete.cases(mtnew),]
# set up UI that allows user to pick x and y variables, see a plot,
# brush the plot, and see a table based on the brush
ui <- fluidPage(
titlePanel("Shiny Test"),
sidebarLayout(
sidebarPanel(
selectInput("xvar",
"pick x",
choices = names(mtnew)),
selectInput("yvar",
"pick y",
choices = names(mtnew))),
mainPanel(
plotOutput("myplot",
brush = brushOpts(id = "plot_brush")),
tableOutput("mytable")
)
)
)
server <- function(input, output) {
output$myplot <- renderPlot({
#ggplot(data = mtnew) +
ggplot(data = mtnew_complete) +
geom_point(aes(x = !!rlang::sym(input$xvar),
y = !!rlang::sym(input$yvar)))
})
output$mytable <- renderTable({
#brush_out <- brushedPoints(mtnew, input$plot_brush)
brush_out <- brushedPoints(mtnew_complete, input$plot_brush)
})
}
# Complete app with UI and server components
shinyApp(ui, server)