I am new to working with shiny package. I am trying to use it to display a ggplot2 graph. I get no errors with my code, however data points are not appearing on the graph. When I select the variables from ui, the axes labels changes accordingly but the data is not added to the plot.
Thank you,
Code:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("P-value", "P-adjust"),
selected = "P-adjust"),
selectInput(inputId = "x" ,
label = "X-axis:",
choices = c("FC", "Mean_Count_PD"),
selected = "FC")
),
mainPanel(plotOutput(outputId = "scatterplot"))
))
server <- function(input, output)
{
output$scatterplot <- renderPlot({
ggplot(data = mir, aes(input$x,input$y)) + geom_point()
})
}
The issue is that you have to tell ggplot that your inputs are names of variables in your dataset. This could be achieved e.g. by making use of the .data pronoun, i.e. instead of using input$x which is simply a string use .data[[input$x]] which tells ggplot that by input$x you mean the variable with that name in your data:
As you provided no data I could not check but this should give you the desired result:
library(shiny)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("P-value", "P-adjust"),
selected = "P-adjust"),
selectInput(inputId = "x" ,
label = "X-axis:",
choices = c("FC", "Mean_Count_PD"),
selected = "FC")
),
mainPanel(plotOutput(outputId = "scatterplot"))
))
server <- function(input, output) {
output$scatterplot <- renderPlot({
ggplot(data = mir, aes(.data[[input$x]], .data[[input$y]])) + geom_point()
})
}
shinyApp(ui, server)
Related
I should create in my shiny app this conditions:
In the UI setup add a selectInput field: the first argument is
the name (how to access the selection in the server setup, we will
call this "species"), the second argument is the label (appears on
the app), and the third argument should list the choices: here we
want to choose between the three different species (can you
obtain the three choices from the data directly?).
I receive this error in my code:
I receive this error:
Error in match.arg(position) : 'arg' must be NULL or a character vector
CODE:
library(shiny)
library(palmerpenguins)
library(ggplot2)
# Define UI for application that draws a plot
ui <- fluidPage(
# Application title
titlePanel("Penguins"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput(inputId = "VarX",
label = "Select X-axis Variable",
choices = list("flipper_length_mm","species","island",
"bill_length_mm","bill_depth_mm","body_mass_g",
"sex","year")),
selectInput(inputId = "VarY",
label = "Select Y-axis Variable",
choices = list("flipper_length_mm","species","island",
"bill_length_mm","bill_depth_mm","body_mass_g",
"sex","year")),
selectInput(
inputId = "varColor",
label = "Color",
choices = c("species"),
selected = "species")),
selectInput(
inputId = "species",
label = "select species",
choices = list("adelie","gentoo","chinstrap")),
# Show a plot
mainPanel(
plotOutput("scatter")
)
)
)
#Define server logic required to draw a scatter
server <- function(input, output) {
pengu <- reactive({ggplot(penguins,
aes(y = bill_depth_mm, x = bill_length_mm))+
geom_point(aes(color = .data[[input$species]]))})
output$scatter <- renderPlot({
pengu()
})
}
# Run the application
shinyApp(ui = ui, server = server)
I am trying to plot using ggplot in R shiny. I want to upload data and any variable can be used for plotting. I am trying to keep aes() dynamically. I tried a few examples example 1, but dint work for me. Here is my code:
library(shiny)
library(shinydashboard)
library(readxl)
library(DT)
library(dplyr)
library(ggplot2)
# Define UI for application that draws a histogram
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Upload data File',
accept=c('text/csv','.xlsx',
'text/comma-separated-values,text/plain',
'.csv'))),
mainPanel(
DT::dataTableOutput('contents')
)
),
tabPanel("First Type",
pageWithSidebar(
headerPanel('Visualization of Dengue Cases'),
sidebarPanel(
selectInput('xcol', 'X Variable', ""),
selectInput('ycol', 'Y Variable', "", selected = "")
),
mainPanel(
plotOutput('MyPlot')
)
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output,session) {
data <- reactive({
req(input$file1)
inFile <- input$file1
df <- read_excel(paste(inFile$datapath, sep=""), 1)
updateSelectInput(session, inputId = 'xcol', label = 'X Variable',
choices = names(df), selected = names(df))
updateSelectInput(session, inputId = 'ycol', label = 'Y Variable',
choices = names(df), selected = names(df)[2])
return(df)
})
output$contents <- DT::renderDataTable({
data()
},options = list(pageLength = 10, width="100%", scrollX = TRUE))
output$MyPlot <- renderPlot({
select_quo <- quo(input$MyPlot_select)
data %>%
mutate(user_input = !!select_quo) %>%
ggplot(aes(fill=user_input, y=user_input, x= user_input)) +
geom_bar( stat="identity")
})
}
# Run the application
shinyApp(ui = ui, server = server)
Can use any data set, such as Diamond dataset.
Also kindly help in allowing all types of formats (.csv, .txt,.xls) of data. As of now, only .xls is acceptable.
There are several issues with your code.
You use data instead of data() in the renderPlot
There is no input input$MyPlot_select.
Using quo and !! will not give the desired result. Instead you could simply use the .data pronoun if your column names are strings.
Add req at the beginning of renderPlot.
This said your renderPlot should look like so:
output$MyPlot <- renderPlot({
req(input$xcol, input$ycol)
x <- input$xcol
y <- input$ycol
fill <- input$xcol
ggplot(data(), aes(x = .data[[x]], y = .data[[y]], fill=.data[[fill]])) +
geom_col()
})
For the second part of your question. To make your app work for different types of input files you could get the file extension using e.g. tools::file_ext and use the result in switch statement.
Full reproducible code:
library(shiny)
library(shinydashboard)
library(readxl)
library(DT)
library(dplyr)
library(ggplot2)
ui <- fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Upload data File",
accept = c(
"text/csv", ".xlsx",
"text/comma-separated-values,text/plain",
".csv"
)
)
),
mainPanel(
DT::dataTableOutput("contents")
)
),
tabPanel(
"First Type",
pageWithSidebar(
headerPanel("Visualization of Dengue Cases"),
sidebarPanel(
selectInput("xcol", "X Variable", ""),
selectInput("ycol", "Y Variable", "", selected = "")
),
mainPanel(
plotOutput("MyPlot")
)
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
data <- reactive({
req(input$file1)
inFile <- input$file1
type <- tools::file_ext(inFile$name)
filename <- inFile$datapath
df <- switch(type,
"xlsx" = read_excel(filename),
"csv" = read_csv(filename),
"tsv" = read_tsv(filename))
updateSelectInput(session,
inputId = "xcol", label = "X Variable",
choices = names(df), selected = names(df)
)
updateSelectInput(session,
inputId = "ycol", label = "Y Variable",
choices = names(df), selected = names(df)[2]
)
return(df)
})
output$contents <- DT::renderDataTable({
data()
}, options = list(pageLength = 10, width = "100%", scrollX = TRUE))
output$MyPlot <- renderPlot({
req(input$xcol, input$ycol)
x <- input$xcol
y <- input$ycol
fill <- input$xcol
ggplot(data(), aes(x = .data[[x]], y = .data[[y]], fill=.data[[fill]])) +
geom_col()
})
}
# Run the application
shinyApp(ui = ui, server = server)
I am creating a shiny app with some tabs and I am using the shinycssloaders package in order to show a spinner AFTER pressing the actionButton. I saw this post because I was having the same problem... I followed the solution that it was given to the post, but as I my app is different (it has tabPanels, it doesn't work properly, the spinner still apears).
For example, if you click on "Show the plot" in the first tab (selection) and then you want to want to do the log2 transformation o calculate the square root (3rd tab, calculations), before clicking the actionButton the spinner appears and the plot updates. It happens the same when you want to change the titles (2nd tab).
Does anyone know how to fix it?
Thanks very much in advance
The code:
library(shiny)
library(magrittr)
library(DT)
library(ggplot2)
library(shinycssloaders)
new_choices <- setNames(names(mtcars), names(mtcars))
ui <- fluidPage(
# Application title
titlePanel("My shiny app"),
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel("Selection",
selectInput("x_axis", "Choose x axis",
choices = new_choices),
selectInput("y_axis", "Choose y axis",
choices = new_choices),
hr(),
),
tabPanel("Titles",
hr(),
textInput(inputId = "title", "You can write the title:", value = "This is the title"),
textInput(inputId = "xlab", "You can re-name the x-axis:", value = "x-axis...."),
textInput(inputId = "ylab", "You can re-name the y-axis:", value = "y-axis ...."),
),
tabPanel("Calculations",
hr(),
checkboxInput("log2", "Do the log2 transformation", value = F),
checkboxInput("sqrt", "Calculate the square root", value = F),
)
),
actionButton(inputId = "drawplot", label = "Show the plot")
),
# Show a plot of the generated distribution
mainPanel(
# plotOutput("plot")
uiOutput("spinner"),
)
)
)
server <- function(input, output, session) {
data <- reactive({
mtcars
})
filtered_data <- reactive({
data <- data()
if(input$log2 == TRUE){
data <- log2(data+1)
}
if(input$sqrt == TRUE){
data <- sqrt(data)
}
return(data)
})
observeEvent(input$drawplot, {
output$spinner <- renderUI({
withSpinner(plotOutput("plot"), color="black")
})
output$plot <- renderPlot({
Sys.sleep(3)
ggplot() +
geom_point(data = filtered_data(),
aes_string(x = input$x_axis, y = input$y_axis)) +
xlab(input$xlab) +
ylab(input$ylab) +
ggtitle(input$title)
})
})
}
shinyApp(ui, server)
Is it OK like this? I'm not sure to understand all your requirements. To avoid the spinner at the start-up, I use a conditionalPanel. In the server code, I did some changes. It is not recommended to define some output inside an observer.
library(shiny)
library(magrittr)
library(ggplot2)
library(shinycssloaders)
new_choices <- setNames(names(mtcars), names(mtcars))
ui <- fluidPage(
# Application title
titlePanel("My shiny app"),
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel(
"Selection",
selectInput("x_axis", "Choose x axis",
choices = new_choices),
selectInput("y_axis", "Choose y axis",
choices = new_choices),
hr(),
),
tabPanel(
"Titles",
hr(),
textInput(inputId = "title", "You can write the title:", value = "This is the title"),
textInput(inputId = "xlab", "You can re-name the x-axis:", value = "x-axis...."),
textInput(inputId = "ylab", "You can re-name the y-axis:", value = "y-axis ...."),
),
tabPanel(
"Calculations",
hr(),
checkboxInput("log2", "Do the log2 transformation", value = F),
checkboxInput("sqrt", "Calculate the square root", value = F),
)
),
actionButton(inputId = "drawplot", label = "Show the plot")
),
# Show a plot of the generated distribution
mainPanel(
conditionalPanel(
condition = "input.drawplot > 0",
style = "display: none;",
withSpinner(plotOutput("plot"))
)
)
)
)
server <- function(input, output, session) {
data <- reactive({
mtcars
})
filtered_data <- reactive({
data <- data()
if(input$log2 == TRUE){
data <- log2(data+1)
}
if(input$sqrt == TRUE){
data <- sqrt(data)
}
return(data)
})
gg <- reactive({
ggplot() +
geom_point(data = filtered_data(),
aes_string(x = input$x_axis, y = input$y_axis)) +
xlab(input$xlab) +
ylab(input$ylab) +
ggtitle(input$title)
}) %>%
bindEvent(input$drawplot)
output$plot <- renderPlot({
Sys.sleep(3)
gg()
})
}
shinyApp(ui, server)
You need to isolate the expressions that you don't want to trigger the rendering event inside renderPlot
library(shiny)
library(magrittr)
library(DT)
library(ggplot2)
library(shinycssloaders)
new_choices <- setNames(names(mtcars), names(mtcars))
ui <- fluidPage(
# Application title
titlePanel("My shiny app"),
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel("Selection",
selectInput("x_axis", "Choose x axis",
choices = new_choices),
selectInput("y_axis", "Choose y axis",
choices = new_choices),
hr(),
),
tabPanel("Titles",
hr(),
textInput(inputId = "title", "You can write the title:", value = "This is the title"),
textInput(inputId = "xlab", "You can re-name the x-axis:", value = "x-axis...."),
textInput(inputId = "ylab", "You can re-name the y-axis:", value = "y-axis ...."),
),
tabPanel("Calculations",
hr(),
checkboxInput("log2", "Do the log2 transformation", value = F),
checkboxInput("sqrt", "Calculate the square root", value = F),
)
),
actionButton(inputId = "drawplot", label = "Show the plot")
),
# Show a plot of the generated distribution
mainPanel(
# plotOutput("plot")
uiOutput("spinner"),
)
)
)
server <- function(input, output, session) {
data <- reactive({
mtcars
})
filtered_data <- reactive({
data <- data()
if(input$log2 == TRUE){
data <- log2(data+1)
}
if(input$sqrt == TRUE){
data <- sqrt(data)
}
return(data)
})
observeEvent(input$drawplot, {
output$spinner <- renderUI({
withSpinner(plotOutput("plot"), color="black")
})
output$plot <- renderPlot({
Sys.sleep(3)
ggplot() +
geom_point(data = isolate(filtered_data()),
aes_string(x = isolate(input$x_axis), y = isolate(input$y_axis))) +
xlab(isolate(input$xlab)) +
ylab(isolate(input$ylab)) +
ggtitle(isolate(input$title))
})
})
}
shinyApp(ui, server)
Read more about shiny reactivity and isolation: https://shiny.rstudio.com/articles/isolation.html
I'd like to use check box input to allow to show different island levels (within the categorical variable selected for the x-axis) with separate boxplots and different colors with a legend. But if this check box is not selected, I just want to show boxplot without fill=legend that is:
ggplot(dat(), aes_string(x = isolate(input$xaxis), y = input$yaxis)) +
geom_boxplot()
This R code is what I tried to use but It didn't work. Could you please help me to solve or tell me what makes error with my R code?
Thank you in advance
library(shiny)
library(palmerpenguins)
library(ggplot2)
library(dplyr)
penguin <- penguins
penguin$year <- as.factor(penguin$year)
ui <- fluidPage(
titlePanel("Data Visualisation of Penguins Data"),
sidebarPanel(
selectInput("yaxis",
label = "Choose a y-axis variable to display",
choices = list("bill_length_mm",
"bill_depth_mm",
"flipper_length_mm",
"body_mass_g"),
selected = "bill_length_mm"),
selectInput("xaxis",
label = "Choose a x-axis variable to display",
choices = c("species",
"sex",
"year"),
selected = "sex"),
checkboxGroupInput("islandlevels",
label = "Check to display different island levels",
choices = c("island"),
selected = NULL),
br(), br(),
selectInput("species",
label = "Choose species to view separate plot",
choices = list("Adelie",
"Chinstrap",
"Gentoo"),
selected = NULL)),
mainPanel(
plotOutput("plot1"),
br(), br(),
plotOutput("plot2")
)
)
server <- function(input, output){
dat <- reactive({
if(input$xaxis == "sex") penguin[!is.na(penguin$sex),] else penguin
})
output$plot1 <- renderPlot({
if(input$islandlevels == "island") {
req(penguin, input$xaxis, input$yaxis)
ggplot(dat(), aes_string(x = isolate(input$xaxis), y = input$yaxis, fill=island)) +
geom_boxplot()
}
if(input$islandlevels = NULL) {
req(penguin, input$xaxis, input$yaxis)
ggplot(dat(), aes_string(x = isolate(input$xaxis), y = input$yaxis)) +
geom_boxplot()}
})
}
shinyApp(ui = ui, server = server)
As long as you don't want any other checkbox inputs you could use a checkboxInput instead of a checkboxGroupInput which makes checking a bit easier.
One issue in your server was that you used island instead of "island". Additionally you can simplify your code a little bit by using fill <- if (input$islandlevels) "island" which will return NULL is the the checkbox was not checked and "island" otherwise. This way you can handle both case with only one ggplot statement .
The full reproducible code:
library(shiny)
library(palmerpenguins)
library(ggplot2)
library(dplyr)
penguin <- penguins
penguin$year <- as.factor(penguin$year)
ui <- fluidPage(
titlePanel("Data Visualisation of Penguins Data"),
sidebarPanel(
selectInput("yaxis",
label = "Choose a y-axis variable to display",
choices = list("bill_length_mm",
"bill_depth_mm",
"flipper_length_mm",
"body_mass_g"),
selected = "bill_length_mm"),
selectInput("xaxis",
label = "Choose a x-axis variable to display",
choices = c("species",
"sex",
"year"),
selected = "sex"),
checkboxInput("islandlevels",
label = "Check to display different island levels",
value = FALSE),
br(), br(),
selectInput("species",
label = "Choose species to view separate plot",
choices = list("Adelie",
"Chinstrap",
"Gentoo"),
selected = NULL)),
mainPanel(
plotOutput("plot1"),
br(), br(),
plotOutput("plot2")
)
)
server <- function(input, output){
dat <- reactive({
if(input$xaxis == "sex") penguin[!is.na(penguin$sex),] else penguin
})
output$plot1 <- renderPlot({
req(penguin, input$xaxis, input$yaxis)
fill <- if (input$islandlevels) "island"
ggplot(dat(), aes_string(x = isolate(input$xaxis), y = input$yaxis, fill = fill)) +
geom_boxplot()
})
}
shinyApp(ui = ui, server = server)
I am tying to create an R shiny app and I would like to have two selectInput i.e. data set name and column name. Right now, I am able to get data set names in the first Input but I am not able to create dependent column selectIput (whose list will depend upon data set selected). Please guide.
require(shiny)
require(MASS)
a <- data(package = "MASS")[3]
b <- a$results[,3]
ui <- fluidPage(
sidebarPanel(width = 2,
selectInput(inputId = "dsname",label = "Select Dataset:",choices = c(b)),
colnames <- names("dsname"),
selectInput(inputId = "columns", label = "Choose columns",
choices = c(colnames))
)
)
server <- function(input,output) {}
shinyApp(ui <- ui, server <- server)
In order to have "responsive" elements in Shiny, you need to wrap your expressions for computing the responsive elements in reactive({...}).
You could use renderUI in your server() and uiOutput in your ui() with something like this. Here is an example I had built for using some of R's data sets (iris, mtcars, and diamonds):
library(shinythemes)
library(shiny)
library(ggplot2)
ui <- fluidPage(theme = shinytheme("superhero"),
titlePanel("Welcome to Responisve Shiny"),
sidebarLayout(
sidebarPanel(
selectInput("data", "Dataset:",
choices = c("mtcars", "iris", "diamonds")
),
uiOutput("x_axis"),
uiOutput("y_axis"),
uiOutput("color")
),
mainPanel(
plotOutput("distPlot")
)
)
)
server <- function(input, output) {
output$x_axis <- renderUI({
col_opts <- get(input$data)
selectInput("x_axis2", "X-Axis:",
choices = names(col_opts))
})
output$y_axis <- renderUI({
cols2 <- reactive({
col_opts2 <- get(input$data)
names(col_opts2)[!grepl(input$x_axis2, names(col_opts2))]
})
selectInput("y_axis2", "Y-Axis:",
choices = cols2(),
selected = "hp")
})
output$color <- renderUI({
col_opts <- get(input$data)
selectInput("color", "Color:",
choices = names(col_opts),
selected = "cyl")
})
output$distPlot <- renderPlot({
if(input$data == "mtcars"){
p <- ggplot(mtcars, aes_string(input$x_axis2, input$y_axis2, color = input$color)) +
geom_point()
}
if(input$data == "iris"){
p <- ggplot(iris, aes_string(input$x_axis2, input$y_axis2, color = input$color)) +
geom_point()
}
if(input$data == "diamonds"){
p <- ggplot(diamonds, aes_string(input$x_axis2, input$y_axis2, color = input$color)) +
geom_point()
}
print(p)
})
}
shinyApp(ui = ui, server = server)