I use R shiny to create multiple tabs for the scatter plot of different variables in a single app. My code seems alright, but the error says I have not "defined my main panel."
Can someone please help where I have gone wrong, or if my whole approach is inaccurateenter code here, please let me know!
library(shiny)
library(tidyverse)
India <- read.csv("D:/R/Practice 3/Indiadata.csv")
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Deaths vs all variables "),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Deaths", "All variables:",
choices = c("cases"="total_cases","vaccinations"="total_vaccinations",
"people vaccinated"="people_vaccinated","people fully vaccinated"="people_fully_vaccinated",
"total booster"="total_boosters","new vaccinations"="new_vaccinations", "median age"="median_age"))
)
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel(plotOutput("plot1")),
tabPanel(plotOutput("plot2")),
tabPanel(plotOutput("plot3")),
tabPanel(plotOutput("plot4")),
tabPanel(plotOutput("plot5")),
tabPanel(plotOutput("plot6")),
tabPanel(plotOutput("plot7"))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_cases))
})
output$plot2 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_vaccinations))
})
output$plot3 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=people_vaccinated))
})
output$plot4 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=people_fully_vaccinated))
})
output$plot5 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=total_boosters))
})
output$plot6 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=new_vaccinations))
})
output$plot7 <- renderPlot({
ggplot(India,aes(y=total_deaths,x=median_age))
})
}
# Run the application
shinyApp(ui = ui, server = server)
mainPanel is an argument of the sidebarLayout() function. So, you just need to move it up into the sidebarLayout() function:
ui <- fluidPage(
# Application title
titlePanel("Deaths vs all variables "),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("Deaths", "All variables:",
choices = c("cases"="total_cases","vaccinations"="total_vaccinations",
"people vaccinated"="people_vaccinated","people fully vaccinated"="people_fully_vaccinated",
"total booster"="total_boosters","new vaccinations"="new_vaccinations", "median age"="median_age"))
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel(plotOutput("plot1")),
tabPanel(plotOutput("plot2")),
tabPanel(plotOutput("plot3")),
tabPanel(plotOutput("plot4")),
tabPanel(plotOutput("plot5")),
tabPanel(plotOutput("plot6")),
tabPanel(plotOutput("plot7"))
)
)
)
)
Related
I'm exploring shiny and I'm trying to do some app that does the following:
Let the user choose between two (or more) different data.frames (in my example I use mtcars and iris but I'm planning to use some self-made data.frames.
Select some X and Y variables according to the data.frame selected
Plot a simple x-y scatterplot
Code below:
df_list <- list(cars= mtcars, iris= iris)
ui <- fluidPage(
titlePanel("Simple app"),
sidebarLayout(
sidebarPanel(
selectInput("data", "Choose a database",
choices=ls(df_list), selected=ls(df_list[1])),
selectInput("xcol", "Variable X", names(data)),
selectInput("ycol", "Variable Y", names(data))),
mainPanel(
plotOutput(outputId = "plot")
)
)
)
server <- function(input, output) {
selectedData <- reactive( {
data[, c(data$xcol, data$ycol)]
})
output$plot <- renderPlot({plot(selectedData())})
}
shinyApp(ui, server)
I feel I have two problems. The first one is pretty obvious since I can't make the app displays variables according to the data.frame selected. Second one is that I feel I'm missing something in my server function (I guess that's related with my first problem) so no plot is displayed.
Any help will be much appreciated.
You had a few issues. The following should work.
df_list <- list("mtcars", "iris")
ui <- fluidPage(
titlePanel("Simple app"),
useShinyjs(),
sidebarLayout(
sidebarPanel(
selectInput("data", "Choose a database",
choices=df_list, selected=df_list[[1]]),
selectInput("xcol", "Variable X", c()),
selectInput("ycol", "Variable Y", c())),
mainPanel(
plotOutput(outputId = "plot")
,DTOutput("t1")
)
)
)
server <- function(input, output, session) {
mydata <- eventReactive(input$data, {
get(input$data)
})
observeEvent(input$data, {
req(mydata())
choices <- names(mydata())
updateSelectInput(session,"xcol",choices = choices, selected=choices[1])
updateSelectInput(session,"ycol",choices = choices, selected=choices[2])
}, ignoreNULL = FALSE)
output$t1 <- renderDT({mydata()})
output$plot <- renderPlot({
req(mydata(),input$xcol,input$ycol)
if (is.null(mydata()) | !(input$xcol %in% colnames(mydata())) | !(input$ycol %in% colnames(mydata())) ) {
return(NULL)
} else{
selected_df <- mydata() %>% select(input$xcol, input$ycol)
plot(selected_df)
}
})
}
shinyApp(ui, server)
I am struggling in writing this shinyApp. It's main aim is to investigate on the variables of a dataset. First it produces the summary statistics on the selected variable.
In the second part; I want this app to give me the pairplot of the varibles that I have selected in the checkbox in the UI. I have used the dataset IRIS which is available to everyone, but I need the code to be adaptable to other datasets.
Can someone please help me?
library(shiny)
library(plotly)
data(iris)
ui<-fluidPage(
titlePanel("Iris"),
sidebarLayout(
sidebarPanel(
selectInput("var",label="Choose a variable",
choice=list("Sepal.Length"=1, "Sepal.Width"=2, "Petal.Length"=3, "Petal.Width"=4, "Species"=5), selectize=FALSE),
checkboxGroupInput(inputId ="independent",label = "Select independent variables", choices = names(iris)),
mainPanel(
verbatimTextOutput("sum"),
plotlyOutput('plot_id_in_ui ', height = "900px")
)
))
)
server<-function(input,output){
output$sum <- renderPrint({
summary(iris[, as.numeric(input$var)])
})
output$plot_id_in_ui <- renderplot( { "DON'T KNOW HOW TO WRITE THIS PART"
pairplot(iris, varnames, type = "both", penalty.par.val = "lambda.1se",
nvals = c(20, 20), pred.type = "response") } )
})
shinyApp(ui, server)
Maybe this little example can help you. It illustrates how to plot a normal R-Plot and a Plotly-Plot in a ShinyApp:
library(shiny)
library(plotly)
ui <- fluidPage(
titlePanel("Iris"),
sidebarLayout(
sidebarPanel(
selectInput("var",label="Choose a variable",
choice=list("Sepal.Length"=1, "Sepal.Width"=2, "Petal.Length"=3, "Petal.Width"=4, "Species"=5), selectize=FALSE),
checkboxGroupInput(inputId ="independent",label = "Select independent variables", choices = names(iris))
),
mainPanel(
verbatimTextOutput("sum"),
plotOutput("plot"),
plotlyOutput("plotly")
)
)
)
server <- function(input,output) {
output$sum <- renderPrint({
summary(iris[, as.numeric(input$var)])
})
output$plot <- renderPlot({
plot(iris)
})
output$plotly <- renderPlotly({
plot_ly(iris) %>%
add_trace(x=iris$Sepal.Length, y=iris$Sepal.Width, type="scatter", mode="markers")
})
}
shinyApp(ui, server)
I am not sure if Im doing this the right way (I am open for suggestions!). However what I try to do if to create a Shiny app where i can pick a bar and then the bar should be highlighted in the graph.
For this example I use the titanic_train dataset.
I do:
library(shiny)
library(ggplot2)
library(titanic)
library(dplyr)
UI <- fluidPage(
# Application title
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
selectInput("specific_bar", "Pick bar to highlight:",
choices = unique(titanic_train$Embarked))
),
mainPanel(
plotOutput("plot_nice")
)
)
)
Server <- function(input, output) {
filtered <- reactive({
titanic_train$Specific <- ifelse((titanic_train$Embarked == input$specific_bar), 1,0)
})
output$plot_nice <- renderPlot({
ggplot(filtered(), aes_string(x="Embarked", y="Survived", fill = "Specific")) +
geom_bar(stat = "identity")
})
}
shinyApp(ui = UI, server = Server)
Running this however gives me the following error:
ggplot2 doesn't know how to deal with data of class numeric
And the problem really seems to have to do with the filtered() reactive function. Any thoughts on what is going wrong here?
you have to ask for the data.frame object back in the reactive part,
what you were doing is getting a vector back instead of getting another column added to titanic_train.
this should fix it:
library(shiny)
library(ggplot2)
library(titanic)
library(dplyr)
UI <- fluidPage(
# Application title
titlePanel("Hello Shiny!"),
sidebarLayout(
sidebarPanel(
selectInput("specific_bar", "Pick bar to highlight:",
choices = unique(titanic_train$Embarked))
),
mainPanel(
plotOutput("plot_nice")
)
)
)
Server <- function(input, output) {
filtered <- reactive({
titanic_train$Specific <- ifelse((titanic_train$Embarked == input$specific_bar), 1,0)
return(titanic_train)
})
output$plot_nice <- renderPlot({
ggplot(filtered(), aes_string(x="Embarked", y="Survived", fill = "Specific")) +
geom_bar(stat = "identity")
})
}
shinyApp(ui = UI, server = Server)
I've been trying to develop an interactive boxplot with selective input in Shiny.
current code:
library(shiny)
shinyUI(fluidPage(
titlePanel("Sample 1"),
sidebarLayout(
sidebarPanel(
selectInput("p", "Choose your salaries", choices = c("low"='a',"mid"='b',"high"='c',"riches!"='d'), selected = 4)
),
mainPanel(
plotOutput("boxplot")
)
)
))
library(shiny)
read.csv("Salaries.csv")
Categories <- cut (Salaries$TotalPay, breaks = c(0,36466,73678,104359,567595), labels = c("low","mid","high","riches!"))
shinyServer(function(input, output){
output$boxplot <- renderPlot({
if(input$p=='a'){
i<"1"
}
if(input$p=='b'){
i<-"2"
}
if(input$p=='c'){
i<-"3"
}
if(input$p=='d'){
i<- "riches!"
}
boxplot(TotalPay~Categories[i])
})
})
I can't get the boxplot to react to the selection made in the UI. I suspect it has to do with the levels as when I call:
> Categories["riches!"]
[1] <NA>
Levels: low mid high riches!
'
Do i need to add factors to these? Or am I missing the point entirely?
Thanks in advance!
Have a look how to access the column by name. Example below is with mtcars dataset
library(shiny)
ui <- fluidPage(
selectInput("p","p",choices = names(mtcars)),
plotOutput("myplot"))
server <- function(input, output, session) {
output$myplot <- renderPlot({
boxplot(mtcars[,input$p])
})
}
shinyApp(ui, server)
I would like to show in my shiny app a link that directs to the URL generated based on user's input. I don't want to show the full text of the URL. I know the a(href="",label="") function can be used if I know the URL beforehand, but in this case the URL depends on the user's input. The following doesn't work:
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
textInput("state", label = "State", value = "CA", placeholder = "California or CA"),
actionButton("showU","Show map")
),
mainPanel(
conditionalPanel(
condition = "input.showU > 0",
htmlOutput("url"),
a(href=htmlOutput("url"),"Show in Google Map",target="_blank")
)
)
)
)
server <- function(input, output){
observeEvent(input$showU,{
output$url <-renderUI({paste("https://www.google.com/maps/place/", input$state, sep="")})
})
}
shinyApp(ui,server)
I hope I can click on the "Show in Google Map" and be directed to the URL generated on the fly. Please help me, thank you.
You need to use renderUI together with uiOutput to update UI reactively:
library(shiny)
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
textInput("state", label = "State", value = "CA", placeholder = "California or CA"),
actionButton("showU","Show map")
),
mainPanel(
conditionalPanel(
condition = "input.showU > 0",
uiOutput("url")
)
)
)
)
server <- function(input, output){
observeEvent(input$showU,{
output$url <-renderUI(a(href=paste0('https://www.google.com/maps/place/', input$state),"Show in Google Map",target="_blank"))
})
}
shinyApp(ui,server)
If this questions is actually about creating reactive URL links, then HubertL's answer is the way to go.
If you want to keep the map and search funciton all self-contained in the shiny, rather than having to open a new link to Google Maps, you can use my googleway package to achieve the same task
library(shiny)
library(googleway)
ui <- fluidPage(
titlePanel("Show map of a given state"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
google_mapOutput(outputId = "myMap", height = "600px")
)
)
)
server <- function(input, output){
## you need a valid API key from Google Maps
## https://developers.google.com/maps/
map_key <- "your_map_api_key"
output$myMap <- renderGoogle_map({
google_map(key = map_key, search_box = T)
})
}
shinyApp(ui,server)
I used a HTML button for which the url could be generated recursively
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("HTML button"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
HTML(paste0(htmlOutput('url_test')))
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$url_test = renderText({
paste('Go to Google')
})
cultivar_url = reactive({
print('https://www.google.com')
})
}
# Run the application
shinyApp(ui = ui, server = server)