Module in shinyApp not recognize by app.R - r

I want my shinyApp to be modularized.
For this I started with the basics, where I just have the basic app.R and a module plot.R to plot the data.
However, even though there is no error message, the module part is not correctly executed, as after selecting the data and executing the analysis no plot is obtained.
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(bslib)
library(shinybusy) # For busy spinners
library(shinyjs)
# Data
library(readxl)
library(dplyr)
# Plots
library(ggplot2)
# Stats
library(stats) #fisher.test, wilcox.test
library(effsize) #Cohen.d
# Sources
source("plot.R")
not_sel <- "Not Selected"
# User interface
ui <- navbarPage(
title = "Plotter",
windowTitle = "Plotter",
tabPanel(
useShinyjs(),
title = "Plotter",
titlePanel(""),
sidebarLayout(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Plot",
value = 1,
# UI from the plot module
plotUI("Plot1")
)
)
)
)
)
)
# Server
server <- function(input, output, session){
# Dynamic selection of the data
data_input <- reactive({
#req(input$xlsx_input)
#inFile <- input$xlsx_input
#read_excel(inFile$datapath, 1)
iris
})
# We update the choices available for each of the variables
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)
# Server part of the love plot module
plotServer("Plot1")
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)
plotUI <- function(id, label="Plot") {
ns <- NS(id)
tagList(
plotOutput("sel_graph")
)
}
plotServer <- function(id) {
moduleServer(id, function(input, output, session) {
draw_boxplot <- function(data_input, num_var_1, num_var_2){
if(num_var_1 != not_sel & num_var_2 != not_sel){
ggplot(data = data_input, aes(x = .data[[num_var_1]], y = .data[[num_var_2]])) +
geom_boxplot(fill = c("#16558F","#61B0B7","#B8E3FF")) +
theme_bw()
}
}
## BoxPlot -------------------------------------------------------------------
plot_1 <- eventReactive(input$run_button,{
req(data_input())
draw_boxplot(data_input(), num_var_1(), num_var_2())
})
output$sel_graph <- renderPlot(
plot_1()
)
}
)
}

The main issue was that the module couldn't find input$run_button because it has a different namespace. What we need is a way to communicate with the module, that is, passing additional arguments to the module call.
Note: The fill argument passed to ggplot inside the module will provoke that the plot only work for Species variable.
App code:
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(bslib)
library(shinybusy) # For busy spinners
library(shinyjs)
# Data
library(readxl)
library(dplyr)
# Plots
library(ggplot2)
# Stats
library(stats) # fisher.test, wilcox.test
library(effsize) # Cohen.d
# Sources
# source("plot.R")
plotUI <- function(id, label = "Plot") {
tagList(
plotOutput(NS(id, "sel_graph"))
)
}
plotServer <- function(id, data, num_var_1, num_var_2, bttn) {
moduleServer(id, function(input, output, session) {
observe(print(num_var_1()))
plot_1 <- eventReactive(bttn(), {
req(data())
if (isolate(num_var_1()) != not_sel & isolate(num_var_2()) != not_sel) {
ggplot(data = data(), aes(x = get(isolate(num_var_1())), y = get(isolate(num_var_2())))) +
geom_boxplot(fill = c("#16558F", "#61B0B7", "#B8E3FF")) +
theme_bw()
}
})
## BoxPlot -------------------------------------------------------------------
output$sel_graph <- renderPlot(
plot_1()
)
})
}
not_sel <- "Not Selected"
# User interface
ui <- navbarPage(
title = "Plotter",
windowTitle = "Plotter",
tabPanel(
useShinyjs(),
title = "Plotter",
titlePanel(""),
sidebarLayout(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Plot",
value = 1,
# UI from the plot module
plotUI("Plot1")
)
)
)
)
)
)
# Server
server <- function(input, output, session) {
# Dynamic selection of the data
data_input <- reactive({
# req(input$xlsx_input)
# inFile <- input$xlsx_input
# read_excel(inFile$datapath, 1)
iris
})
# We update the choices available for each of the variables
observeEvent(data_input(), {
choices <- c(not_sel, names(data_input()))
updateSelectInput(inputId = "num_var_1", choices = choices)
updateSelectInput(inputId = "num_var_2", choices = select(data_input(), where(is.factor)) %>% names())
})
num_var_1 <- eventReactive(input$run_button, input$num_var_1)
num_var_2 <- eventReactive(input$run_button, input$num_var_2)
# Server part of the love plot module
plotServer("Plot1", data_input, reactive(input$num_var_1), reactive(input$num_var_2), reactive(input$run_button))
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)

Related

Filter dataframe by factors based on users input in Shiny

I want the user of my shinyApp to select a variable, as well as the factors for this variable.
Then, the shinyApp will provide a dataset where the factors are filtered.
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(shinyjs)
# Data
library(readxl)
library(dplyr)
library(rlang)
# Plots
library(ggplot2)
not_sel <- "Not Selected"
ui <- navbarPage(
tabPanel(
"",
fluidPage(
fluidRow(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
uiOutput("binning")
),
# Main panel
mainPanel(
tabsetPanel(
tabPanel(
"Plot",
br(),
plotOutput("plot_1"),
textOutput("test"),
uiOutput("levels")
)
)
)
)
)
)
)
server <- function(input, output){
# Load data and update inputs
data_input <- reactive({
#req(input$xlsx_input)
#inFile <- input$xlsx_input
#read_excel(inFile$datapath, 1)
warpbreaks
})
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 <- reactive(input$num_var_1)
num_var_2 <- reactive(input$num_var_2)
# Select factors to display
output$levels <- renderUI({
req(data_input(), input$num_var_1)
e <- unique(data_input()[[input$num_var_1]])
awesomeCheckboxGroup(inputId="levels", label = "Factor level order", choices = setNames(as.numeric(e), e), inline = TRUE)
})
data_plot <- reactive({
req(data_input(), input$num_var_1, input$num_var_2)
#df <- data_input()
df<- data_input()[data_input()[[input$num_var_1]] %in% input$levels, ]
df
})
output$test <- renderPrint(data_input())
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)
However, the filtering function is not working, and I don't see why.
More precisely, this line of code:
df<- data_input()[data_input()[[input$num_var_1]] %in% input$levels, ]
In the case of the attached image, for example, the dataset should have the values for the factor F.
However, nothing is printed.
Please check the values of input$levels.
Try this
data_plot <- reactive({
req(data_input(), input$num_var_1, input$num_var_2)
#df <- data_input()
df<- data_input()[as.numeric(data_input()[[input$num_var_1]]) %in% input$levels, ]
df
})
output$plot_1 <- renderPlot({
if (is.null(input$levels)) return(NULL)
plot(data_plot())
})

Compute dynamic pvalue in rshiny based on users variable selection

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)

Compute statistic for more than two levels dynamically

I would like my shinyApp to be able to compute statistics for all the combination of factor levels of a given variable.
In the case of Iris dataset, for example, the user would be able to select the categorical variable (species) and the continous variable (any other).
Then, the user would be able to select the factor of the categorical variable (versicolor, virginica, setosa). The shinyApp then will compute the statistic for all the other factors against the chosen one.
More precisely this statistic is the cohens d (cohen.d, effsize package) which is one of the most common way of measuring effect size.
This is the code that I have:
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(shinyjs)
# Data
library(readxl)
library(dplyr)
library(vcd)
library(effsize)
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(),
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_stats',
label = 'Select factors',
choices = c(a), selected=a[3], multiple = F,
options = list(`actions-box` = TRUE))
}
})
multiple_cohens <- function(response, factor) {
cohen.d(response, factor, paired = TRUE)$estimate
}
dat_cohen <- reactive({
req(data_input(),input$num_var_1,input$num_var_2,input$selected_factors_stats)
#with(data_input(), multiple_wilcox(input$num_var_2, relevel(input$num_var_1, input$selected_factors)))
df <- data_input()
df <- df %>% drop_na(input$num_var_2)
fac <- unique(data_input()[[input$num_var_1]][data_input()[[input$num_var_1]] != input$selected_factors_stats])
df$new <- df[[input$num_var_1]]
newlevels <- c(input$selected_factors_stats,as.character(fac))
df$new <- factor(df$new, levels=newlevels)
with(df, multiple_cohens(df[[input$num_var_2]], new))
})
output$stats <- renderPrint({
dat_cohen()
})
}
shinyApp(ui = ui, server = server)
The dat_cohen is working properly, however, I didn't find a way of iterating with multiple_cohens

Display of the color coded by Hex in pickerInput (rshiny)

I have a shinyApp that allows the user to create a barplot and dynamically select the colors of the plot.
As you can see, this app is working fine, however, as the colors are represented by the Hex code, there is no really a way of telling which color is it until you have plot it,
hece I would like a way to improve the display of the colors selection.
In the webpage (https://ssc.wisc.edu/shiny/users/jstruck2/colorpicker/) there is an example of what I want, although there is no code.
And here you can find a RepEx of my app.
# Shiny
library(shiny)
library(shinyWidgets)
library(shinyjqui)
library(shinyjs)
library(DT)
# Data
library(readxl)
library(dplyr)
library(vcd)
# Plots
library(ggplot2)
not_sel <- "Not Selected"
ui <- navbarPage(
title = "Plotter",
windowTitle = "Plotter",
tabPanel(
"Plotter",
fluidPage(
fluidRow(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
br(),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
# Main panel
mainPanel(
tabsetPanel(
tabPanel(
"Plot",
br(),
plotOutput("plot_1"),
uiOutput("factor"),
)
)
)
)
)
)
)
################# --------------------------------------------------------------
# Server
################# --------------------------------------------------------------
server <- function(input, output){
# Dynamic selection of the data
data_input <- reactive({
#req(input$xlsx_input)
#inFile <- input$xlsx_input
#read_excel(inFile$datapath, 1)
Arthritis
})
# We update the choices available for each of the variables
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)
# data
data_discrete_plot <- reactive({
req(data_input(), input$num_var_1, input$num_var_2)
df <- data_input()
df1 <- as.data.frame(prop.table(table(df[[input$num_var_1]], df[[input$num_var_2]]), margin = 1))
df1
})
output$factor <- renderUI({
#req(input$num_var_2,data_input())
if (is.null(input$num_var_2) | (input$num_var_2=="Not Selected")) return(NULL)
df <- data_input()
uvalues <- unique(df[[input$num_var_2]])
n <- length(uvalues)
choices <- as.list(uvalues)
myorder <- as.list(1:n)
mycolors <- list("#727CA3", "#464653", "#638CAE", "#836A61", "#889328", "#F5AF22", "#DF564B", "#6B4A8C", "#CE7EB8")
nk <- length(mycolors) ## to repeat colors when there are more bars than the number of colors
tagList(
div(br()),
div(
lapply(1:n, function(i){
k <- i %% nk
if (k==0) k=nk
pickerInput(paste0("colorvar",i),
label = paste0(uvalues[i], ": " ),
choices = list(# DisplayOrder = myorder,
FillColor = mycolors),
selected = list( i, mycolors[[k]]),
multiple = T,
options = list('max-options-group' = 1, `style` = "btn-primary"))
})
)
)
})
#observe({print(input$colorvar1)})
output$t1 <- renderDT(data_discrete_plot())
# Function for printing the plots
draw_barplot <- function(data_input) {
n <- length(unique(data_input[,"Var2"]))
val <- list()
myvaluesx <- lapply(1:n, function(i) {
input[[paste0("colorvar",i)]]
if (i==1) val <- list(input[[paste0("colorvar",i)]])
else val <- list(val,input[[paste0("colorvar",i)]])
})
print(myvaluesx)
ggplot(data = data_input, aes(x = Var1, y = Freq, fill = factor(Var2), label = round(Freq, 3))) +
geom_bar(stat = "identity") +
#scale_fill_discrete(guide = guide_legend(fill = myvaluesx, reverse = TRUE)) +
scale_fill_manual(values = unlist(myvaluesx)) +
ylim(0, 1) +
theme_bw()
}
## BarPlot -------------------------------------------------------------------
plot_1 <- eventReactive(input$run_button,{
req(data_input())
draw_barplot(data_discrete_plot())
})
output$plot_1 <- renderPlot(plot_1())
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)

Change the order of factors inside plots based on user input in rshiny

Is it possible to change the order of the plots in Rshiny based on usersinput?
I have a dataframe with two variables, 'morale' ('high', 'medium' and 'low') and casualties (numerical variable), and I want to know if there are differences between the groups, for which I'm going to to some boxplots.
This shinyapp (RepEx below), allows you to plot this two variables:
Casualties <- c(13, 34,23,123,0,234,3,67,87,4)
Morale <- c("High", "Medium", "Low","High", "Medium", "Low","High", "Medium", "Low", "High")
romans <- data.frame(Casualties, Morale)
# Shiny
library(shiny)
library(shinyWidgets)
# Data
library(readxl)
library(dplyr)
# Data
library(effsize)
# Objects and functions
not_sel <- "Not Selected"
main_page <- tabPanel(
title = "Romans",
titlePanel("Romans"),
sidebarLayout(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
br(),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Plot",
plotOutput("plot_1")
)
)
)
)
)
# Function for printing the plots with two different options
# When there is not a selection of the biomarker (we will take into account var_1 and var_2)
# And when there is a selection of the biomarker (we will take into account the three of them)
draw_boxplot <- function(data_input, num_var_1, num_var_2){
print(num_var_1)
if(num_var_1 != not_sel & num_var_2 != not_sel){
ggplot(data = data_input, aes(x = .data[[num_var_1]], y = .data[[num_var_2]])) +
geom_boxplot() +
theme_bw()
}
}
################# --------------------------------------------------------------
# User interface
################# --------------------------------------------------------------
ui <- navbarPage(
main_page
)
################# --------------------------------------------------------------
# Server
################# --------------------------------------------------------------
server <- function(input, output){
data_input <- reactive({
#req(input$xlsx_input)
#inFile <- input$xlsx_input
#read_excel(inFile$datapath, 1)
romans
})
# We update the choices available for each of the variables
observeEvent(data_input(),{
choices <- c(not_sel, names(data_input()))
updateSelectInput(inputId = "num_var_1", choices = choices)
updateSelectInput(inputId = "num_var_2", choices = choices)
})
# Allow user to select the legion
num_var_1 <- eventReactive(input$run_button, input$num_var_1)
num_var_2 <- eventReactive(input$run_button, input$num_var_2)
## Plot
plot_1 <- eventReactive(input$run_button,{
#print(input$selected_factors)
req(data_input())
df <- data_input()
draw_boxplot(df, num_var_1(), num_var_2())
})
output$plot_1 <- renderPlot(plot_1())
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)
enter image description here
As you can see in the plot above, the variables are ordered alphanumerically (this is because they are treated as a 'character', and not as a 'factor', although this is not so important right now).
What I would like is a way of changing the order of the plots, so the user could manually select which factor (High, Medium or Low) wants in the first place, etc.
Is there a way of doing this?
Let's draw a boxplot with variable factor levels with the example dataset iris so we can drag the button order with the mouse:
library(tidyverse)
library(shiny)
library(shinyjqui)
ui <- fluidPage(
orderInput(inputId = "levels", label = "Factor level order",
items = c("setosa", "versicolor", "virginica")),
plotOutput(outputId = "plot")
)
server <- function(input, output) {
data <- reactive({
mutate(iris, Species = Species %>% factor(levels = input$levels))
})
output$plot <- renderPlot({
qplot(Species, Sepal.Width, geom = "boxplot", data = data())
})
}
shinyApp(ui, server)
Using shinyjqui
Casualties <- c(13, 34,23,123,0,234,3,67,87,4)
Morale <- c("High", "Medium", "Low","High", "Medium", "Low","High", "Medium", "Low", "High")
romans <- data.frame(Casualties, Morale)
# Shiny
library(shiny)
library(shinyWidgets)
# Data
library(readxl)
library(dplyr)
# Data
library(effsize)
# drag
library(shinyjqui)
#plotting
library(tidyverse)
# Objects and functions
not_sel <- "Not Selected"
main_page <- tabPanel(
title = "Romans",
titlePanel("Romans"),
sidebarLayout(
sidebarPanel(
title = "Inputs",
fileInput("xlsx_input", "Select XLSX file to import", accept = c(".xlsx")),
selectInput("num_var_1", "Variable X axis", choices = c(not_sel)),
selectInput("num_var_2", "Variable Y axis", choices = c(not_sel)),
orderInput('morale_order', 'Morale', items = unique(Morale)),
br(),
actionButton("run_button", "Run Analysis", icon = icon("play"))
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Plot",
plotOutput("plot_1")
)
),verbatimTextOutput('order')
)
)
)
# Function for printing the plots with two different options
# When there is not a selection of the biomarker (we will take into account var_1 and var_2)
# And when there is a selection of the biomarker (we will take into account the three of them)
draw_boxplot <- function(data_input, num_var_1, num_var_2){
print(num_var_1)
if(num_var_1 != not_sel & num_var_2 != not_sel){
ggplot(data = data_input, aes(x = .data[[num_var_1]], y = .data[[num_var_2]])) +
geom_boxplot() +
theme_bw()
}
}
################# --------------------------------------------------------------
# User interface
################# --------------------------------------------------------------
ui <- navbarPage(
main_page
)
################# --------------------------------------------------------------
# Server
################# --------------------------------------------------------------
server <- function(input, output){
data_input <- reactive({
#req(input$xlsx_input)
#inFile <- input$xlsx_input
#read_excel(inFile$datapath, 1)
romans |>
mutate(Morale = Morale |> factor(levels = input$morale_order))
})
# We update the choices available for each of the variables
observeEvent(data_input(),{
choices <- c(not_sel, names(data_input()))
updateSelectInput(inputId = "num_var_1", choices = choices)
updateSelectInput(inputId = "num_var_2", choices = choices)
})
# Allow user to select the legion
num_var_1 <- eventReactive(input$run_button, input$num_var_1)
num_var_2 <- eventReactive(input$run_button, input$num_var_2)
## Plot
plot_1 <- eventReactive(input$run_button,{
#print(input$selected_factors)
req(data_input())
df <- data_input()
draw_boxplot(df, num_var_1(), num_var_2())
})
output$plot_1 <- renderPlot(plot_1())
# test what is there
output$order <- renderPrint(input$morale_order)
}
# Connection for the shinyApp
shinyApp(ui = ui, server = server)

Resources