R-Shiny - Change file by SelectInput and re-run code - r

I am working on a shiny app. I am sorry if I am unclear, but I am at the very beginning with shiny.
Basically, I have a long list of functions that are sourced into the shiny app before starting the server and the ui.
All these functions rely on a single database which is imported in the source file through an readRDS call.
source("calculations.R")
dash <- shinyApp(
server = function(input, output) {
output$element1 <- renderText({db1$var1[[1]]})
...
},
ui = shinyUI(fluidPage(
dashboardPage(
options = list(sidebarExpandOnHover = TRUE),
header = dashboardHeader(title="Title"),
sidebar = dashboardSidebar(minified = TRUE, collapsed = TRUE),
body = dashboardBody(
fluidRow(
column(width=8, box(width=12, title="Hello", valueBox(width=6, color="yellow", textOutput("element1")))
...
),
),
controlbar = dashboardControlbar(selectInput(inputId='selectfile','Select File',choice = list.files('folder/'))),
title = "DashboardPage"
)))
)
dash
The structure of the source file is pretty much the following:
db1 <- readRDS("folder/file1.rds")
Now, what I am trying to do is to let the user select another file from the folder (let's say, file2.rds) through the selectInput in the dashboard.
This should be following by:
replacing the old db1 with the new one (i.e., db1 <- readRDS("folder/file2.rds"))
update all the following code in the calculations.R file (I've created a calculations2.R file, which is a copy of calculations.R, but without the first line of code which read the file and put into the db1 object, as it would overwrite the new file)
update the output variables in the server
update the data in the UI.
I've tried several solution. Currently I am stuck with the following (in which calculations2.R contains the same code of calculations.R, without the db1 <- readRDS("folder/file1.rds") call at the beginning of the file):
shinyApp(
server = function(input, output) {
db1 <- reactive({readRDS(file.path("folder",input$selectfile))})
observeEvents(input$selectfile, {source("calculations2.R")})
output$element1 <- renderText({db1$var1[[1]]})
...
},
However, everytime I select another file from the selectInput, it get me an error from the functions in the calculations2.R, as if db1 was not appropriately loaded.

Related

How to integrate code into a shiny app and upload files?

I'm new to shiny and I would like your advice on a requirement that I have at my office. I apologize in advance for not providing more information or code at the moment.
I have currently coded a R script that does the following:
Import 7 excel files with read_excel:
File 1 will go to dataset 1
File 2 will go to dataset 2
File 3,4,5,6,7 will go to dataset 3 by using lapply
Does a whole lot of data cleaning, formatting, parsing and ordering
Merges everything together and creates a final excel and txt files with specific formatting
Im requiring a shiny web app that:
Provides 3 different upload boxes for the user. One for each type of file (1 / 2 / 3,4,5,6,7)
Internally saves the uploaded files so the code i already have can use them for its processing
Lets the user download the 2 output files made by my code to the computer
If possible, show a log window on the app so the user can know if something goes wrong with the code execution
Datasets visualization is not required
I might be asking a lot. I will appreciate if you just can give me some lights in how i can start working on this. I would like not to modify my current code, if possible (can i have shiny acquire the files, and call my code so it can process them?)
Here is a minimal example showing uploading files, processing them, and downloading them.
For simplicity I've used 3 inputs and a single output.
If you want to notify a user that something has happened, you can use showNotification()
library(shiny)
ui <- fluidPage(
#File Upload Boxes
fileInput("myfileinput_1", label = "Upload File 1", accept = ".csv"),
fileInput("myfileinput_2", label = "Upload File 2", accept = ".csv"),
fileInput("myfileinput_3", label = "Upload File 3", accept = ".csv"),
#Button
actionButton("mybutton", label = "Process Uploaded Files"),
#Table Showing Processed Data
tableOutput("mytable"),
#Download Buttons
downloadButton("myfiledownload", label = "Download Processed File")
)
server <- function(input, output, session) {
#A reactive dataframe to store our outputfile
reactives <- reactiveValues(
df_output = NULL
)
#Runs when button is pressed
observeEvent(input$mybutton, {
#Check that all 3 files are selected before loading
if(!is.null(input$myfileinput_1) & !is.null(input$myfileinput_2) & !is.null(input$myfileinput_3)) {
#Load input files
df_input_1 <- read.csv(input$myfileinput_1$datapath)
df_input_2 <- read.csv(input$myfileinput_2$datapath)
df_input_3 <- read.csv(input$myfileinput_3$datapath)
#Use input to create an output (we're just using a simple example)
reactives$df_output <- data.frame(
input = c("Input 1", "Input 2", "Input 3"),
rows = c(nrow(df_input_1), nrow(df_input_2), nrow(df_input_3))
)
showNotification("Files Successfully Processed", type = "message")
} else {
showNotification("Ensure all three files are selected before loading", type = "error")
}
})
#Table Output
output$mytable <- renderTable({
reactives$df_output
})
#Download handler
output$myfiledownload <- downloadHandler(
filename = "mydata.csv",
content = function(file) {write.csv(reactives$df_output, file, row.names = FALSE)}
)
}
shinyApp(ui, server)

Excel data distribution with Shiny

I am not good at English, so sentences may be wrong.
I want to distribute excel files prepared in advance to users. Is it possible to realize such a system with shiny? No problem with .zip.
Thank you
ui.R
shinyUI(
fluidPage(
downloadButton('downloadData', 'Excel Download')
)
)
server.R
shinyServer(function(input, output) {
output$downloadData <- downloadHandler(
filename = "distribution.xlsx",
content = "distribution_excel"
)
})
Yes, it is possible and you were nearly there. Below is a minimal working example. I assume that your .xlsx file is located in the same folder as your app.R. Notice that I have created the app in a single R file as opposed to two separate files.
The trick to getting the file to download is to use a function for the content inside of downloadHandler(). Specifically we are using the base function file.copy(). Clicking the button should now download the file: distribution.xlsx. This file can obviously be exchanged with a zip file.
If you want different users to access different Excel files, you can write an additional function inside of your server function that passes the file argument to the downloadHandler().
# Load packages ----
pkgs <- c("shiny")
invisible(lapply(pkgs, require, character.only = TRUE))
# Set up the UI ----
ui <- fluidPage(
# Define your download button
downloadButton(
outputId = "downloadData",
label = "Excel Download"
)
)
# Set up the server side ----
server <- function(input, output, session) {
# Define the download handler with function() for content.
output$downloadData <- downloadHandler(
filename = "distribution.xlsx",
content = function(file) {
file.copy("distribution.xlsx", file)
}
)
}
# Combine into an app ----
shinyApp(ui = ui, server = server)

Is there a simple way to generate a section of UI from an uploaded dataset?

I am setting up a shiny application that asks for a dataset, asks for information about said data set, and then runs a series of analytic models on said data set, taking into account information about the dataset (for example, the names of variables to adjust for in a regression). The app starts with a simple UI with a data upload input. Once the user has uploaded their data, I would like the UI to dynamically add a new section that asks the user to select a subset of variables from the column labels of their dataset.
I am working with RStudio Server via a Linux AWS machine.
My app is generated as an add-on to another R package that serves as a wrapper for most of the statistical functions I require. Since the app is quite large, the UI is composed of some standard text and a series of functions that call tabItems for the UI.
In the example below, the UI has a standard data upload user input. In addition to this I have attempted to use shiny::renderUI on the server side to take the user-provided dataset, read the columns, and return the set of columns via shiny::varSelectInput(). Unfortunately, my app does not provide this new input after uploading the data.
ui_data_1 <- function(){
y<-tabItem(tabName = "load_dat",
shiny::tabsetPanel(type = "tabs",
# Data upload ---- -
h2("Data"),
p("Please upload your data file"),
shiny::fileInput(
inputId = "data_file", label = "Upload patient data file (.csv Only)",
accept = c(".csv")
),
h2("Treatment"),
p("Instructions for treatment"),
shiny::uiOutput("variables"))
)
)
return(y)
}
server_data_1 <- function(){
y <- shiny::renderUI({
inFile <- input$data_file
# Load data
if (is.null(inFile)) {
df <- shiny::reactive({NULL})
} else {
df <- shiny::reactive({read.csv(inFile$datapath, header = input$header)})
}
varnames <- colnames(df())
shiny::varSelectInput(
inputId = "treat",
label = "Treatment Variable",
data = c(varnames)
)
})
return(y)
}
#UI.R
body <- shinydashboard::dashboardBody(
ui_data_1()
)
ui <- shinydashboard::dashboardPage(header, sidebar, body, skin = "black")
#Server.R
server <- function(input, output) {
output$variables <- server_data_1()
}
shiny::shinyApp(ui, server)
The app loads properly, as does the data upload menu. When I upload the data, I receive a notification indicating that the upload was successful. The label associated with inputId = "treat" is visible the entire time. However, the variable selection menu does not populate after uploading the data as expected. Perhaps I've done something wrong. Thanks in advance for any advice.

shinydashboard: execute data import x seconds after pressing a button

BACKGROUND
I'm building a shiny dashboard in Data Science Studio where a user has to choose a file they want to process from the selectizeInput and then press Submit actionButton. Once the button is pressed, it starts a backend process to determine what category the file falls into and what workflow it should follow (different workflows contain different cleaning steps and final outputs). Once the workflow completes, I want to display the final output in DT::renderDataTable.
DESIRED OUTPUT
I would like my shiny app to
show no data before the input is chosen
time, let's say, 30 seconds from the moment someone clicks the Submit button to actually picking up the dataset
MINIMAL WORKING EXAMPLE
How could I implement it in this simple app?
UI
library(shiny)
library(shinydashboard)
library(DT)
library(dataiku)
path <- dkuManagedFolderPath("receiver") #folder with the files to choose from
dashboardPage(
dashboardHeader(title = "Catchy Title"),
dashboardSidebar(
selectizeInput("file", "Select File",
list.files(path)),
actionButton("submit", "Submit")
),
dashboardBody(
fluidRow(
box(h2("Show Data"),
div(style = 'overflow-x: scroll', DT::dataTableOutput('mytable')),
width = 12)
)
)
)
SERVER
library(dataiku)
library(shiny)
library(shinydashboard)
library(DT)
library(dplyr)
shinyServer(function(input, output) {
file_name <- reactive({
req(input$file)
})
####
# run the process that takes the file name to pass it to
# the global environment, which triggers the conditional workflow
# and may result in different data outputs
####
## AFTER the process runs (approx. 30 seconds after pressing the submit button)
# I want the shiny app to follow this logic:
if(is.null(nrow(try(dkuReadDataset("intermediate_dataset"))[1]))){
df <- dkuReadDataset("final_data1")
} else{
df <- dkuReadDataset("final_data2")
}
output$mytable = DT::renderDataTable({
df
})
})
Thanks for the hints!

R Shiny Reactively Display an Image from a list

I am trying to reactively display an image from a list in an R shiny application.
I have many .tiff images stored in the "www" directory of my app. They follow the naming convention OHC_130.tiff, OHC_131.tiff, OHC_132.tiff, IHC_133.tiff, Deiter_134.tiff, OHC_135.tiff etc...
I also have a vector containing all of these names
ImgID_Vector <- as.vector(c("OHC_130", "OHC_131", "OHC_132", "IHC_133", "Deiter_134", "OHC_135")
I would like to make a selectable input dropdown list like this where a user can select an image and then click the submit button to make the image appear below. I have set this up for the ui.r but i am not sure how to make it work on the server side.
#ui.r
library(shiny)
library(shinydashboard)
dashboardBody(
tabItems(
tabItem(tabName = "dt",
h2("Select an image"),
fluidRow(
box(title="This is a searchable database of images", solidHeader = TRUE,status = "primary"),
selectInput("input$ImageIDVariable1", label = h4("Enter your image of interest"), choices = (ImgID_Vector), multiple = TRUE),
submitButton("Submit"),
imageOutput("ImageID_Image")
)
)
)
Conceptually I know that on the server side I need to connect the user input from the UI side to the actual image in the "www" folder. I should be able to do this using reactive inputs and renderImage I think. But I am not sure how to write the render image command to achieve the desired result.
#server.r
#This is the data that contains the choices for the dropdown menu
ImgID_Vector <- readRDS("ImgID_Vector.RDS")
shinyServer(function(input, output) {
# This is where I am struggling, with the render image command
output$ImageID_Image <- renderImage({
filename <- normalizePath(file.path('./www',
paste(input$ImageIDVariable1, '.tiff', sep='')))
list(src = filename)
}, deleteFile = FALSE)
}
#This is where I have the reactive input variable
ImageIDVariable1 <- reactive({input$ImageIDVariable1})
})
Thanks for your help!
Hi argument inputId from your selectInput is wrong, it should be "ImageIDVariable1", not input$ImageIDVariable1.
In ui.R :
selectInput(inputId = "ImageIDVariable1", label = h4("Enter your image of interest")
In server.R
input$ImageIDVariable1
Moreover :
You should use this in a script called global.R or at least in ui.R :
ImgID_Vector <- readRDS("ImgID_Vector.RDS")
And you should not use multiple = TRUE because renderImage can only render one image at a time.
And you should put a selected choice by default, if not renderImage will search an image which doesn't exist.

Resources