I am trying to make data available in R shiny for survival analysis. In other words, some people might not have the access to upload data in R shiny. For those people, I want to provide some dataset so that they can use the data. Does anyone know how to make some data available in R shiny? This is the code:
library(shiny)
library(datasets)
library(survival)
options(shiny.maxRequestSize = 70 * 1024 ^ 2)
shinyUI(fluidPage(
titlePanel("Data Visualization"),
tabsetPanel(
tabPanel(
"Upload File",
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput(
'file1',
'Choose RData File',
accept = c(".Rdata")
),
selectInput(
"dataset", "Select the dataset", choices = c("LUAD_RNASeq",
"LUSC_RNASeq")
)
),
mainPanel(
p("Head of the data"),
tableOutput('contents'))
)
),
tabPanel(
"Summary",
pageWithSidebar(
headerPanel('Summary of Variable'),
sidebarPanel(
# "Empty inputs" - they will be updated after the data is
uploaded
#selectInput('row', 'Row', ""),
selectInput('col', 'Column', "", selected = "")
),
mainPanel(
#p("Summary for the row"),
#verbatimTextOutput("row_summary"),
p("Summary for the column"),
verbatimTextOutput("col_summary")
)
)
),
tabPanel(
"Survival",
plotOutput("surPlot")
),
tabPanel(
"Scatter Plot",
pageWithSidebar(
headerPanel('Scatter Plot'),
sidebarPanel(
selectInput('col1', 'Column1', "", selected = ""),
selectInput('col2', 'Column2', "", selected = "")
),
mainPanel(
plotOutput("scaPlot")
)
)
),
tabPanel(
"Univariate Cox Regression",
pageWithSidebar(
headerPanel('Univariate Cox Regression'),
sidebarPanel(
selectInput('col3', 'Cox Variable', "", selected = "")
),
mainPanel(
verbatimTextOutput("reg_summary"),
plotOutput("reg_Plot")
)
)
),
tabPanel(
"AFT Regression",
pageWithSidebar(
headerPanel('Log normal AFT regression'),
sidebarPanel(
selectInput('col4', 'AFT Variable', "", selected = "")
),
mainPanel(
p("To do the AFT regression, the survival time can not be
zero"),
verbatimTextOutput("aft_summary")
#plotOutput("aft_Plot")
)
)
),
tabPanel(
"Glmnet Analysis",
p("To do Glmnetplot, the survival time can not be zero or NA
value"),
plotOutput("GlmnetPlot")
)
)
))
library(shiny)
library(datasets)
library(survival)
library(ggplot2)
library(survminer)
library(GGally)
library(glmnet)
library(rsconnect)
options(shiny.maxRequestSize = 70 * 1024 ^ 2)
load_obj <- function(f)
{
env <- new.env()
nm <- load(f, env)[1]
env[[nm]]
}
shinyServer(function(input, output, session) {
data <- reactive({
req(input$file1)
df<-load_obj(input$file1$datapath)$merged.dat
# Update inputs (you could create an observer with both updateSel...)
# You can also constraint your choices. If you wanted select only
numeric
# variables you could set "choices = sapply(df, is.numeric)"
# It depends on what do you want to do later on.
updateSelectInput(
session,
inputId = 'row',
label = 'Row',
choices = 1:nrow(df),
selected = 1
)
updateSelectInput(
session,
inputId = 'col',
label = 'Column',
choices = names(sapply(df, is.numeric)),
selected = names(df)[2]
)
updateSelectInput(
session,
inputId = 'col1',
label = 'Column1',
choices = names(sapply(df, is.numeric)),
selected = names(df)[4]
)
updateSelectInput(
session,
inputId = 'col2',
label = 'Column2',
choices = names(sapply(df, is.numeric)),
selected = names(df)[5]
)
updateSelectInput(
session,
inputId = 'col3',
label = 'Cox Variable',
choices = names(sapply(df, is.numeric)),
selected = names(df)[5]
)
updateSelectInput(
session,
inputId = 'col4',
label = 'AFT Variable',
choices = names(sapply(df, is.numeric)),
selected = names(df)[5]
)
return(df)
})
output$contents <- renderTable({
df<-data()
return (head(df[,1:10]))
})
output$row_summary <- renderPrint({
df<-data()
row<-as.numeric(df[input$row, 2:ncol(df)])
summary(row)
})
output$col_summary <- renderPrint({
df<-data()
column<-df[,input$col]
summary(column)
})
output$surPlot <- renderPlot({
plot.survival <- function(data)
{
ggsurv(survfit(
Surv(data$OS, data$status) ~ 1,
type = "kaplan-meier",
conf.type = "log-log"
),
main = "Survival Plot(K-M estimate)")
}
print(plot.survival(data()))
})
output$scaPlot <- renderPlot({
df<-data()
column1<-df[,input$col1]
column2<-df[,input$col2]
plot(column1, column2)
})
output$reg_summary <-renderPrint({
df=data()
column3=df[,input$col3]
res.cox=coxph(Surv(df$OS,df$status) ~ column3, data=df)
summary(res.cox)
})
output$reg_Plot <- renderPlot({
df=data()
column3=df[,input$col3]
res.cox=coxph(Surv(df$OS,df$status) ~ column3, data=df)
ggsurvplot(survfit(res.cox), palette = "#2E9FDF",ggtheme =
theme_minimal(),data = df)
})
output$aft_summary <-renderPrint({
df=data()
column4=df[,input$col4]
res.aft=survreg(Surv(df$OS,df$status) ~ column4, data=df,
dist="lognormal")
summary(res.aft)
})
output$GlmnetPlot <- renderPlot({
df=data()
y1=cbind(time=df$OS,status=df$statu)
x1 <- subset(df, select = -c(bcr,OS, status))
x1=data.matrix(x1, rownames.force = NA)
fit1=glmnet(x1,y1,family="cox")
plot(fit1)
})
# datasetInput <- eventReactive(input$update, {
# switch(input$dataset,
# "rock" = rock,
# "pressure" = pressure,
# "cars" = cars)
# })
# output$aft_Plot <- renderPlot({
# df=data()
# df=df[-c(which(df$OS==0)),]
# column4=df[,input$col4]
# res.aft=survreg(Surv(df$OS,df$status) ~ column4, data=df,
dist="lognormal")
# ggsurvplot(survfit(res.aft), color = "#2E9FDF",ggtheme =
theme_minimal(),data = df)
# })
})
If you have a CSV file with your data, include that in the folder your Shiny app is in, and call:
mydata <- read.csv("your_file.csv")
If you save your data as an R variable as an Rds:
mydata <- readRDS("your_file.Rds")
Related
I have a dataframe with several variables. One of them is continous and the other one is categorical.
I want to obtain wilcoxon test between these two variables, which is basically a metric to compare the difference between two groups of samples.
This is really easy when you know which factors you want to compare.
In base r this is pretty easy with the script:
# Pairwise Wilcox Test allow us to obtain multiple tests at the same time
multiple_wilcox <- function(response, factor) {
pairwise.wilcox.test(response, factor, p.adjust.method = "none")$p.value[, 1]
}
# By default, tests are found against the reference level
with(iris, multiple_wilcox(Sepal.Length, Species))
#> versicolor virginica
#> 8.345827e-14 6.396699e-17
# ... which can be changed with `relevel()`
with(iris, multiple_wilcox(Sepal.Length, relevel(Species, "virginica")))
I would like to implement this in shiny, so I would get all the p-values for a variable selected by the user.
This reactive function should do the work, as it's just the same.
dat <- reactive({
with(data_input(), multiple_wilcox(input$num_var_2, relevel(input$num_var_1, input$selected_factors)))
})
But I'm getting the error:
I don't find where this error is coming from, as the data should be the same.
Here is the RepEx.
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(shinyjs)
# Data
library(readxl)
library(dplyr)
library(vcd)
# Plots
library(ggplot2)
not_sel <- "Not Selected"
ui <- navbarPage(
tabPanel(
"",
fluidPage(
fluidRow(
sidebarPanel(
title = "Inputs",
fileInput("csv_input", "Select CSV file to import", accept = c(".csv")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
uiOutput("binning"),
br(),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
# Main panel
mainPanel(
tabsetPanel(
tabPanel(
"Plot",
br(),
verbatimTextOutput("test"),
uiOutput("var_stats"),
br(),
verbatimTextOutput("stats")),
)
)
)
)
)
)
server <- function(input, output){
# Load data and update inputs
data_input <- reactive({
#req(input$csv_input)
#inFile <- input$csv_input
#read.csv(inFile$datapath, 1)
iris
})
observeEvent(data_input(),{
choices <- c(not_sel, names(data_input()))
updateSelectInput(inputId = "num_var_1", choices = choices)
updateSelectInput(inputId = "num_var_2", choices = choices)
})
num_var_1 <- eventReactive(input$run_button, input$num_var_1)
num_var_2 <- eventReactive(input$run_button, input$num_var_2)
output$var_stats <- renderUI({
req(input$num_var_1, data_input())
if (input$num_var_1 != not_sel) {
a <- unique(data_input()[[input$num_var_1]])
pickerInput(inputId = 'selected_factors',
label = 'Select factors',
choices = c(a), selected=a[3], multiple = F,
options = list(`actions-box` = TRUE))
}
})
multiple_wilcox <- function(response, factor) {
pairwise.wilcox.test(response, factor, p.adjust.method = "none")$p.value[, 1]
}
dat <- reactive({
with(data_input(), multiple_wilcox(input$num_var_2, relevel(input$num_var_1, input$selected_factors)))
})
output$test <- renderPrint({
dat()
})
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)
As relevel() is not working in shiny, you may need to change the factor manually as shown below.
not_sel <- "Not Selected"
ui <- navbarPage(
tabPanel(
"",
fluidPage(
fluidRow(
sidebarPanel(
title = "Inputs",
fileInput("csv_input", "Select CSV file to import", accept = c(".csv")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
uiOutput("binning"),
br(),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
# Main panel
mainPanel(
tabsetPanel(
tabPanel(
"Plot",
br(),
verbatimTextOutput("test"),
uiOutput("var_stats"),
br(),
verbatimTextOutput("stats")),
)
)
)
)
)
)
server <- function(input, output){
# Load data and update inputs
data_input <- reactive({
#req(input$csv_input)
#inFile <- input$csv_input
#read.csv(inFile$datapath, 1)
iris
})
observeEvent(data_input(),{
choices <- c(not_sel, names(data_input()))
updateSelectInput(inputId = "num_var_1", choices = choices)
updateSelectInput(inputId = "num_var_2", choices = choices)
})
num_var_1 <- eventReactive(input$run_button, input$num_var_1)
num_var_2 <- eventReactive(input$run_button, input$num_var_2)
output$var_stats <- renderUI({
req(input$num_var_1, data_input())
if (input$num_var_1 != "Not Selected") {
a <- as.list(as.character(unique(data_input()[[input$num_var_1]])))
pickerInput(inputId = 'selected_factors',
label = 'Select factors',
choices = list(Factor=a), selected=a[[3]], multiple = F,
options = list(`actions-box` = TRUE))
}
})
multiple_wilcox <- function(response, factor) {
pairwise.wilcox.test(response, factor, p.adjust.method = "none")$p.value[, 1]
}
dat <- eventReactive(input$run_button, {
req(data_input(),input$num_var_1,input$num_var_2,input$selected_factors)
#with(data_input(), multiple_wilcox(input$num_var_2, relevel(input$num_var_1, input$selected_factors)))
df <- data_input()
fac <- unique(data_input()[[input$num_var_1]][data_input()[[input$num_var_1]] != input$selected_factors])
df$new <- data_input()[[input$num_var_1]]
newlevels <- c(input$selected_factors,as.character(fac))
df$new <- factor(df$new, levels=newlevels)
with(df, multiple_wilcox(df[[input$num_var_2]], new))
})
output$test <- renderPrint({
dat()
})
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)
I have plotted scatterplot for each country, and I am trying to add a correlation coefficient under the scatterplot, but I keep getting errors saying "Selections can't have missing values." even after using na.rm
Can someone help me with this??
I appreciate any help you can provide.
data link EuropeIndia
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
library(plotly)
library(DT)
library(tidyverse)
library(car)
library(ggpubr)
covid <- read.csv("EuropeIndia.csv")
title <- tags$a(href='https://ourworldindata.org/covid-vaccinations?country=OWID_WRL',
'COVID 19 Vaccinations')
# Define UI for application
ui <- fluidPage(
headerPanel(title = title),
# Application title
titlePanel("COVID vaccinations: Deaths Vs All variables"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("location", "1. Select a country",
choices = covid$location, selectize = TRUE, multiple = FALSE),
br(),
helpText("2. Select variables for scatterplot"),
selectInput(inputId = "y", label = "Y-axis:",
choices = c("total_deaths", "new_deaths"),
selected = "Deaths",),
br(),
selectInput(inputId = "x", label = "X-axis:",
choices = names(subset(covid,select = -c(total_deaths,new_deaths,
iso_code, continent,date,location), na.rm =TRUE)),
selectize = TRUE,
selected = "Comparator variables")
),
mainPanel(
textOutput("location"),
#plotOutput("Scatterplot"),
tabsetPanel(
type = "tabs",
tabPanel("Scatterplot", plotlyOutput("scatterplot"),
verbatimTextOutput("correlation"),
verbatimTextOutput("interpretation")),
tabPanel("Summary of COVID data", verbatimTextOutput("summary")),
tabPanel("Dataset", DTOutput("dataset")))
)
)
)
# Define server logic
server <- function(input, output) {
output$location <- renderPrint({locationfilter <- subset(covid, covid$location == input$location)})
output$summary <- renderPrint({summary(covid)})
output$dataset <- renderDT(
covid, options = list(
pageLength = 50,
initComplete = JS('function(setting, json) { alert("done"); }')
)
)
output$scatterplot <- renderPlotly({
ggplotly(
ggplot(subset(covid, covid$location == input$location),
aes(y = .data[[input$y]], x = .data[[input$x]],col = factor(stringency_index)))+
geom_smooth()+geom_point()+labs(col ="Stringency Index")
)
})
output$correlation <- renderText({
x= subset(covid, covid$location == input$location) %>% dplyr::select(as.numeric(!!!input$x, na.rm =TRUE))
y= subset(covid, covid$location == input$location) %>% dplyr::select(as.numeric(!!!input$y, na.rm = TRUE))
var(x,y, na.rm = T, use)
cor(x,y, method = 'pearson', na.rm =T)
})
}
# Run the application
shinyApp(ui = ui, server = server)
First of all you should select just one Country from the selection list.
For error checking I propose you the next code.
library(shiny)
library(plotly)
library(DT)
library(tidyverse)
library(car)
library(ggpubr)
covid <- read.csv("EuropeIndia.csv")
title <- tags$a(href='https://ourworldindata.org/covid-vaccinations?country=OWID_WRL',
'COVID 19 Vaccinations')
# Define UI for application
ui <- fluidPage(
headerPanel(title = title),
# Application title
titlePanel("COVID vaccinations: Deaths Vs All variables"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectInput("location", "1. Select a country",
choices = covid$location[1], selectize = TRUE, multiple = FALSE),
br(),
helpText("2. Select variables for scatterplot"),
selectInput(inputId = "y", label = "Y-axis:",
choices = c("total_deaths", "new_deaths"),
selected = "Deaths",),
br(),
selectInput(inputId = "x", label = "X-axis:",
choices = names(subset(covid,select = -c(total_deaths,new_deaths,
iso_code, continent,date,location), na.rm =TRUE)),
selectize = TRUE,
selected = "Comparator variables")
),
mainPanel(
textOutput("location"),
#plotOutput("Scatterplot"),
tabsetPanel(
type = "tabs",
tabPanel("Scatterplot", plotlyOutput("scatterplot"),
verbatimTextOutput("correlation"),
verbatimTextOutput("interpretation")),
tabPanel("Summary of COVID data", verbatimTextOutput("summary")),
tabPanel("Dataset", DTOutput("dataset")))
)
)
)
# Define server logic
server <- function(input, output) {
output$location <- renderPrint({locationfilter <- subset(covid, covid$location == input$location)})
output$summary <- renderPrint({summary(covid)})
output$dataset <- renderDT(
covid, options = list(
pageLength = 50,
initComplete = JS('function(setting, json) { alert("done"); }')
)
)
output$scatterplot <- renderPlotly({
ggplotly(
ggplot(subset(covid, covid$location == input$location),
aes(y = .data[[input$y]], x = .data[[input$x]],col = factor(stringency_index)))+
geom_smooth()+geom_point()+labs(col ="Stringency Index")
)
})
output$correlation <- renderText({
x <- covid[covid$location == input$location, input$x]
y <- covid[covid$location == input$location, input$y]
xy = data.frame(x,y)
xy = xy[complete.cases(xy),]
var(xy)
cor(xy,method = 'pearson')
})
}
# 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
As the title describes, I'm simply trying to create a shiny application that allows the user to generate linear regression plots based on an imported csv file. After importing the file the dropdown for the variables of interest should be dynamically updated.
As the code below shows, I'm able to accomplish that with mtcars but I'm not able to do the same with an imported files that would have different dependent and independent variables .
Thank you for your help
data(mtcars)
cols <- sort(unique(names(mtcars)[names(mtcars) != 'mpg']))
ui <- fluidPage(
titlePanel("Build a Linear Model for MPG"),
sidebarPanel(
#fluidRow(
#column(4,
#tags$h3('Build a Linear Model for MPG'),
fileInput(
inputId = "filedata",
label = "Upload data. csv",
accept = c(".csv")
),
fileInput(
inputId = "filedata1",
label = "Upload data. csv",
accept = c(".csv")
),
selectInput('vars',
'Select dependent variables',
choices = cols,
selected = cols[1:2],
multiple = TRUE)
#)
), #sidebarpanel
mainPanel( column(4, verbatimTextOutput('lmSummary')),
column(4, plotOutput('diagnosticPlot')))
) #fluidpage
server <- function(input, output) {
data <- reactive({
req(input$filedata)
read.csv(input$filedata$datapath) %>% rename_all(tolower) %>%
filter(driver_name == input$driver_name & county == input$county & model == input$model)
})
lmModel <- reactive({lm(sprintf('mpg ~ %s', paste(input$vars, collapse = '+')),
data = mtcars)})
# lmModel <- reactive({lm(sprintf('mpg ~ %s', paste(input$vars, collapse = '+')),
# data = mtcars)})
output$lmSummary <- renderPrint({
summary(lmModel())
})
output$diagnosticPlot <- renderPlot({
par(mfrow = c(2,2))
plot(lmModel())
})
}
shinyApp(ui = ui, server = server)```
To dynamically select x and y axis variables, you can try the following
ui <- fluidPage(
titlePanel("Build a Linear Model"),
sidebarPanel(
fileInput(
inputId = "filedata",
label = "Upload data. csv",
multiple = FALSE,
accept = c(".csv"),
buttonLabel = "Choosing ...",
placeholder = "No files selected yet"
),
uiOutput("xvariable"),
uiOutput("yvariable")
), #sidebarpanel
mainPanel( #DTOutput("tb1"),
fluidRow(column(6, verbatimTextOutput('lmSummary')) , column(6, plotOutput('diagnosticPlot')))
)
) #fluidpage
server <- function(input, output) {
data <- reactive({
req(input$filedata)
inData <- input$filedata
if (is.null(inData)){ return(NULL) }
mydata <- read.csv(inData$datapath, header = TRUE, sep=",")
})
output$tb1 <- renderDT(data())
output$xvariable <- renderUI({
req(data())
xa<-colnames(data())
pickerInput(inputId = 'xvar',
label = 'Select x-axis variable',
choices = c(xa[1:length(xa)]), selected=xa[1],
options = list(`style` = "btn-info"))
})
output$yvariable <- renderUI({
req(data())
ya<-colnames(data())
pickerInput(inputId = 'yvar',
label = 'Select y-axis variable',
choices = c(ya[1:length(ya)]), selected=ya[2],
options = list(`style` = "btn-info"))
})
lmModel <- reactive({
req(data(),input$xvar,input$yvar)
x <- as.numeric(data()[[as.name(input$xvar)]])
y <- as.numeric(data()[[as.name(input$yvar)]])
if (length(x) == length(y)){
model <- lm(x ~ y, data = data(), na.action=na.exclude)
}else model <- NULL
return(model)
})
output$lmSummary <- renderPrint({
req(lmModel())
summary(lmModel())
})
output$diagnosticPlot <- renderPlot({
req(lmModel())
par(mfrow = c(2,2))
plot(lmModel())
})
}
shinyApp(ui = ui, server = server)
Addressing the dynamic menu:
Your selectInput element must be placed in the server section for it to be reactive. Things in the ui section are basically static. Use a uiOutput in the ui section and renderUI in the server section.
ui section (in place of selectInput block): uiOutput("var_select_ui")
server section (add):
output$var_select_ui <- renderUI({
cols <- colnames(data())
selectInput(
'vars',
'Select dependent variables',
choices = cols,
selected = cols[1:2],
multiple = TRUE
)
})