I am building a shiny application with several tabs, each tab takes a user input (unique(data_in$cat), and generates some type of graph. The problem occurs in the second tab--for some reason, it does not generate the graph that is specified by data2. The first graph on the first tab is being displayed correctly.I see no error when I run this code, so I don't know where to start debugging!
library(shiny)
library(openxlsx)
library(ggplot2)
data_in <- read.xlsx("www/dem_data_clean.xlsx")
ui <- navbarPage(title = "Data",
tabPanel(title = "Over-all trends",
plotOutput("Histall"),
selectInput("Indall","Demographic Variable of Interest",choices = unique(data_in$cat))
),
tabPanel(title = "2017-2018"),
plotOutput("Hist17"),
selectInput("Ind17","Demographic Variable of Interest",choices = unique(data_in$cat))
)
server <- function(input, output, session) {
data1 <- reactive({
a <- subset(data_in,cat==input$Indall)
return(a)
})
data2 <- reactive({
a <- subset(data_in,cat==input$Ind17)
return(a)
})
output$Histall <- renderPlot({
ggplot(data1(), aes(x=Year,y=value, group =name, color=name)) + geom_line(stat = "identity") +
ylab("Percent of Population")
})
output$Hist17 <- renderPlot({
data2() %>%
filter(Year=="2017-18") %>%
ggplot(aes(name, value)) + geom_bar(stat = "identity")
})
}
shinyApp(ui, server)
Any suggestions to what I am doing wrong? I've tried playing around with different things for a few hours now to no avail!
The UI code is not correct, second plotOutput and selectInput are not within second tabPanel. It works if you fix it :
ui <- navbarPage(title = "Data",
tabPanel(title = "Over-all trends",
plotOutput("Histall"),
selectInput("Indall",
"Demographic Variable of Interest",
choices = unique(data_in$cat))
),
tabPanel(title = "2017-2018",
plotOutput("Hist17"),
selectInput("Ind17",
"Demographic Variable of Interest",
choices = unique(data_in$cat)))
)
Related
I am trying to make an RShiny app that you can pick a gene from a list, and it will display different graphs using that gene's transcripts. However, each gene has a different number of transcripts, so a different number of graphs must be displayed every time a different gene is chosen. How I have it set right now is that when a person chooses a gene, a new table is created with the transcript numbers (data to be plotted) along with a new list of all the transcript names (length of this list is the amount of plots that I need). These are reactive values.
Below, in the server, I made a function that creates the graph that I want, and then I iterate through the creation of the function by indexing into the reactive list of names, so it creates a graph for each name (as each name is a different transcript). Right now, the code iterates through all the names correctly but only displays the last plot. Is there a way to have every plot displayed? I have tried a lot of different things, from renderUI to using local calls, but cannot figure it out.
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("var", label = "Choose a gene to display", names),
mainPanel(
plotOutput("tdot"))
))
server <- function(input, output) {
genename <- reactive({
input$var
})
transTable2 <- reactive ({
cbind(biofluids, select(transTable, starts_with(input$var)))
})
names <- reactive ({
tableBF <- cbind(biofluids, select(transTable, starts_with(input$var)))
n <- colnames(tableBF)
final <- n[-1]
})
createUI <- function(name, table) {
ggplot(table, aes_string(x = "biofluids", y = name))+geom_boxplot(aes(color = biofluids))+
geom_boxplot(aes(fill = biofluids)) + scale_y_log10()+ylab( 'log10 normalized counts')+
ggtitle(name)}
output$tdot <- renderPlot({
lapply(1:length(names()), function(i)
createUI(names()[i], transTable2()))
})
}
# Run the application
shinyApp(ui = ui, server = server)
A reproducible example is as follows with the iris dataset, which would have the user select a category (either "Sepal" or "Petal"), and then create a plot for every column in the dataset that starts with that word:
cats <- c("Sepal", "Petal")
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("var", label = "Choose a category to display", cats),
mainPanel(
plotOutput("tdot"))
))
server <- function(input, output) {
category <- reactive({
input$var
})
iris2 <- reactive ({
select(iris, starts_with(input$var))
})
names <- reactive ({
table2 <- select(transTable, starts_with(input$var))
n <- colnames(table2)
})
createUI <- function(name, table) {
ggplot(table, aes_string(x = "species", y = name))+geom_boxplot(aes(color = species))+
geom_boxplot(aes(fill = species)) + scale_y_log10()+ylab( 'log10 normalized counts')+
ggtitle(name)}
output$tdot <- renderPlot({
lapply(1:length(names()), function(i)
createUI(names()[i], iris2()))
})
}
# Run the application
shinyApp(ui = ui, server = server)
The following code generates dynamic number of outputs with iris data. You should be able to adapt this to your data.
library(shiny)
library(tidyverse)
# Load data
data("iris")
# Add row id
iris2 <- iris %>% mutate(ID = 1:n())
# ui
ui <- fluidPage(
sidebarPanel(
selectInput(inputId = "sel", label = "Select one or more parameters",
choices = names(iris2), multiple = TRUE)
),
mainPanel(
uiOutput("plots")
)
)
# server
server <- function(input, output, session){
# Dynamically generate the plots based on the selected parameters
observe({
req(input$sel)
lapply(input$sel, function(par){
p <- ggplot(iris2, aes_string(x = "ID", y = par)) +
geom_boxplot(aes(fill = Species, group=Species, color=Species)) +
ggtitle(paste("Plot: ", par))
output[[paste("plot", par, sep = "_")]] <- renderPlot({
p
},
width = 380,
height = 350)
})
})
# Create plot tag list
output$plots <- renderUI({
req(input$sel)
plot_output_list <- lapply(input$sel, function(par) {
plotname <- paste("plot", par, sep = "_")
plotOutput(plotname, height = '250px', inline=TRUE)
})
do.call(tagList, plot_output_list)
})
}
shinyApp(ui, server)
It gives the following output:
I went a totally different direction in this project -- the issue I have is down at the end I need to clear out the graph when a different variable is selected. The graph as it is stays the same. Thanks.
I am not even sure how this would be phrased in the documents -- rewriting graphs, dynamic plotting ??? I saw display.removePlot(display.activePlotIndex()) but am not sure about that -- what do I look up to figure this out?
library(shiny)
library(DT)
library(ggplot2)
oboler_data <- read_csv(file = "C:/Users/12083/Desktop/ref.csv")
rdate <- as.Date(oboler_data$DATE,"%m/%d/%y")
ui <- fluidPage(sidebarLayout(
sidebarPanel(
selectInput("dataset", "choose a dataset", c("oboler_data")),
selectInput("column", "Type of Transaction", "placeholder1"),
selectInput("level", "select level", "placeholder2")
),
mainPanel(tableOutput("table"), plotOutput("Histo"))
))
server <- function(input, output, session){
dataset <- reactive({
get(input$dataset)
})
observe({
updateSelectInput(session, "column", choices = names(dataset()))
})
observeEvent(input$column, {
column_levels <- as.character(sort(unique(
dataset()[[input$column]]
)))
updateSelectInput(session, "level", choices = column_levels)
})
output$table <- renderTable({
subset(dataset(), dataset()[[input$column]] == input$level)
})
DF <- data.frame(Name = LETTERS[1:10], Value = rnorm(20), Value2 = runif(20))
output$TableOut <- renderDataTable({
DF
})
output$Histo <- renderPlot({
ggplot(DF, aes(Value)) + geom_histogram(binwidth = 0.1,
fill = "blue", color = "white")
})
}
shinyApp(ui, server)
I think you should use req, as it precludes (and clears!) rendering of a plot if conditions are not met.
library(shiny)
shinyApp(
ui = fluidPage(
checkboxInput("cb", "Plot?"),
sliderInput("cyls", "Cylinders", min = 1, max = 8, value = 4, step = 1),
plotOutput("plt")
),
server = function(input, output, session) {
output$plt <- renderPlot({
req(input$cb, input$cyls)
ggplot(mtcars[mtcars$cyl >= input$cyls,,drop = FALSE],
aes(disp, mpg, color = factor(cyl))) +
geom_point()
})
}
)
The three screenshots above are in sequence: start with "Plot?" deselected, no plot shown; select it, plot appears; deselect it, existing plot disappears.
The way you adapt this to you is to replace the req(input$cb) with something that matches your condition of "clear the plot". (I also included input$cyls here just to prevent larger more-complex apps from reaching the plot block before all inputs have stabilized. Perhaps not required in most apps, but it's a defensive move that carries little consequence if it is overkill, but lots of benefit when it is needed.)
A slight modification on a theme, "telling the user why the plot disappeared". Replace the req with a validate and at least one need:
# req(input$cb, input$cyls)
validate(
need(input$cb, "You deselected \"Plot!\"")
)
I am teaching myself r and shiny and trying to make an interactive bar chart where the user can change the chart based on columns. I keep getting errors with this code. Any help would be appreciated! My data has four columns: v, one, two, three. The first column is characters and the last three are numbers. I want to change the bar chart based on the y axis (columns: one, two and three). Right now, the error I am getting is: missing value where TRUE/FALSE needed.
library(shiny)
library(readr)
library(ggplot2)
data <- read.csv('scoring.csv')
data$v <- as.character(data$v)
ui <- fluidPage(
titlePanel("Scoring"),
sidebarPanel(
selectInput(inputId = "scoring", label = "Select a score:", c("Scoring Method 1", "Scoring Method 2", "Scoring Method 3"))),
mainPanel(
plotOutput(outputId = "bar")
)
)
#browser()
server <- function(input, output) {
new_data <- reactive({
selected_score = as.numeric(input$"scoring")
if (selected_score == "Scoring Method 1"){(data[data$one])}
if (selected_score == "Scoring Method 2"){(data[data$two])}
if (selected_score == "Scoring Method 3"){(data[data$three])}
})
#browser()
output$bar <- renderPlot({
newdata <- new_data()
p <- ggplot(newdata, aes(x=reorder(v, -selected_score), selected_score, y = selected_score, fill=v)) +
geom_bar(stat = 'identity', fill="darkblue") +
theme_minimal() +
ggtitle("Sports")
barplot(p, height = 400, width = 200)
})
}
Run the application
shinyApp(ui = ui, server = server)
You have a few errors in your code. In the server part, please use input$scoring, instead of input$"scoring".
First, in ui selectInput could be defined as
selectInput(inputId = "scoring", label = "Select a score:", c("Scoring Method 1"="one",
"Scoring Method 2"="two",
"Scoring Method 3"="three")))
Second, your reactive dataframe new_data() could be defined as shown below:
new_data <- reactive({
d <- data %>% mutate(selected_score = input$scoring)
d
})
Third, ggplot could be defined as
output$bar <- renderPlot({
newdata <- new_data()
p <- ggplot(newdata, aes(x=v, y = newdata[[as.name(selected_score)]], fill=v)) +
geom_bar(stat = 'identity', position = "dodge", fill="blue") +
theme_bw() +
#scale_fill_manual(values=c("blue", "green", "red")) +
scale_y_continuous(limits=c(0,10)) +
ggtitle("Sports")
p
})
Please note that you had an extra selected_score variable within aes. My suggestion would be to play with it to reorder x, and review some online or youtube videos on R Shiny.
I am new to R Shiny. Actually i have drawn Stacked Barplot using ggplot in my
R code. I want to draw the same using shiny. Below is my R code:
ggplot(data = df, aes(x = OutPut, y = Group, fill = Group)) +
geom_bar(stat = "identity") +
facet_grid(~ Environment)
In my R code it is giving correct results.But i am trying to draw in shiny. Below is my shiny R code.
ui <- fluidPage(theme = shinytheme("lumen"),
titlePanel("Data Analysis"),
selectInput("variable", "Variable:", c("OutPut", "Member", "Levels")),
mainPanel(plotOutput("plot")))
# Define server function
server <- function(input, output){
x = ggplot(data = df, aes(x = variable.names(), y = Group, fill = Group)) +
geom_bar(stat = "identity") +
facet_grid(~ Environment)
plot(x)
}
# Create Shiny object
shinyApp(ui = ui, server = server)
It is throwing an error,here i have created a dropdown box where all the variables have been stored. So when i select one variable, it should plot the Stacked barplot. Could anyone please help me.
Like it was mentioned in the comments, you need to use the rendering functions and actually assign them to the output to get the outputs you need.
I believe an example of using plots in rshiny would help, since it wouldn't make sense to have it in the comments, here it is:
library(shiny)
library(ggplot2)
ui <- fluidPage(titlePanel("Fast Example with mtcars"),
# inputs
selectInput("x", "Choose x:", choices = names(mtcars), selected = 'mpg'),
selectInput("y", "Choose y:", choices = names(mtcars), selected = 'hp'),
selectInput("fill", "Choose fill:", choices = names(mtcars), selected = 'carb'),
mainPanel(
#outputs
h2("Chosen variables are:"),
h4(textOutput("vars")),
plotOutput("plot")))
server <- function(input, output) {
df <- mtcars
# here's how you would use the rendering functions
# notice that I used aes_string
output$plot <- renderPlot({
ggplot(data=df,
aes_string(x= input$x, y= input$y, fill=input$fill)) +
geom_point()
})
output$vars <- renderText(paste0('x: ', input$x, " , ",
'y: ', input$y, " , ",
'fill: ', input$fill))
}
shinyApp(ui = ui, server = server)
The Rshiny tutorial is pretty helpful, you can take a look at it here https://shiny.rstudio.com/tutorial/
I have a shiny application with the following ui:
library(rhandsontable)
library(shiny)
library(ggplot2)
ui = fluidPage(
# App title ----
titlePanel("Tabsets"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs",
tabPanel("Summary", rHandsontableOutput('contents'),
actionButton("saveBtn", "Save changes")
),
tabPanel("Tab",
rHandsontableOutput('contentFinal')),
tabPanel("Dashboard",
plotOutput('dashboard1'))
)
)
)
)
And the following server
library(dplyr)
library(rhandsontable)
options(shiny.maxRequestSize = 9*1024^2)
server = function(input, output) {
values <- reactiveValues()
Post <- c("", "")
list2 <- c(12,13)
df <- data.frame(Post, list2)
output$contents <- renderRHandsontable({
rhandsontable(df, width = 550, height = 300) %>%
hot_col(col = "Post", type = "dropdown")
})
saveData <- eventReactive({input$saveBtn},{
finalDF <- hot_to_r(input$contents)
finalDF$Post <- ifelse(finalDF$Post =="",NA,finalDF$Post)
newDF <- finalDF[complete.cases(finalDF),]
return(newDF)
})
output$contentFinal <- renderRHandsontable(
rhandsontable(saveData())
)
output$dashboard1 <- renderPlot(
ggplot(input$contentFinal, aes(x = Post, y = list2 )) +
geom_bar(stat = "identity")
)
observeEvent(input$saveBtn, saveData())
}
shinyApp(ui = ui, server = server)
The flow is like this:
In the first tab, I bring up data with an empty post column
In this tab, I can add a name for the post and save it.
As soon as I save he rows with values for post become visible in the next tab.
Then the next thing I want to do is to have a visual in the dashboard tab that shows the data. Therefore I create:
output$dashboard1 <- renderPlot(
ggplot(input$contentFinal, aes(x = Post, y = List2 )) +
geom_bar(stat = "identity")
)
This however gives me the following ggplot2 errror:
ggplot2 doesn't know how to deal with data of class list
Any thoughts on what goes wrong here?
The problem is because input$contentFinal is handsontable data. We need to convert it to R object using hot_to_r function.
The ggplot should be plotted using the following:
ggplot(hot_to_r(input$contentFinal), aes(x = Post, y = list2 )) +
geom_bar(stat = "identity")
Hope it helps!