R+Shiny: read file and use its content - r

Please find below an example of a script I found online (probably from Rstudio) to create a simple app to read a variety of flat files and output a table.
I added a bit which creates the file "test_input_file.csv" which the app can read.
I am lost with a very simple task: after reading the csv file, I have a tibble and I render it as a table. How do I access this tibble directly to do something else with it? E.g. plot it with plotly, take some statistics etc...?
Many thanks
library(shiny)
library(tidyverse)
tt <- tibble(AA=seq(10), BB=seq(10)*2, CC=seq(10)*3 )
write_csv(tt, "test_input_file.csv")
rm(tt)
# Define UI for data upload app ----
ui <- fluidPage(
# App title ----
titlePanel("Uploading Files"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv", "space")),
# Horizontal line ----
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t",
Space = " "),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"'),
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
)
# Define server logic to read selected file ----
server <- function(input, output) {
output$contents <- renderTable({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
})
}
# Create Shiny app ----
shinyApp(ui, server)
#> PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
Shiny applications not supported in static R Markdown documents
Created on 2022-03-09 by the reprex package (v2.0.1)

This code loads the file straight into the output table and doesn't really store the raw table anywhere. This snippet of code is actually loading the file:
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
You can use this outside of the renderTable({}) to load the file just as a normal variable and do whatever you want with it.
However, if you set this code straight into the server function, it won't work - since this is a user input, you should set this variable as reactive, so I would do something like this:
df = reactive({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
return(df)
})
Then you can call df() and do whatever you want with it. Ofc it would be nice to add try statements or some checks to make sure the file can be loaded properly, like the in the renderTable({}).
So the server side should look like this:
server <- function(input, output) {
df = reactive({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
return(df)
})
output$contents <- renderTable({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
})
}

Related

Run Render.ui logic only after file has been uploaded

I am trying to run a shiny app with several scripted functions attached. I have a sidebar select input that accesses a variable which is only created after a file is uploaded and the "db_prep" R script is processed. The "db_prep" R script also combines elements of the "full_db" that is first loaded. I have tried to use renderUI to solve this problem but I cant identify where I am going wrong. Ideally, I would like to run the app, upload my file and then run my functions on the uploaded file and full_db to generate the output in the next boxplot tab.
Here is the ui:
#compiled db
full_db <- read.csv("./full_db.csv", header = TRUE, sep = ",", stringsAsFactors = FALSE)
# ui ----
ui <- fluidPage(
theme = shinytheme("superhero"),
titlePanel("Title"),
tabsetPanel(type = "tabs",
tabPanel("File Upload",
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Horizontal line ----
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"'),
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents")
)
)
),
uiOutput("moreControls"),
# Main panel for displaying outputs ----
mainPanel(
h1("Actions"),
plotOutput("plot", width = "100%"))
))
Server:
# server ----
# Define server logic to plot various variables against
server <- function(input, output, session) {
#server logic for file upload tab
output$contents <- renderTable({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
df_x <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
if(is.null(input$file1)){
return(NULL)
}
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
if(input$disp == "head") {
return(head(df_x))
}
else {
return(df_x)
}
})
#server logic for boxplot tab
#required scripts & functions
source("db_prep.R")
source("box_75_test.R")
source("box_80_test.R")
source("box_85_test.R")
source("box_90_test.R")
source("box_95_test.R")
output$moreControls <- renderUI({
if(is.null(input$file1())) return()
tabPanel("Boxplot",
sidebarPanel("output.fileUploaded",
selectInput("variable", "Action:", unique(qc$Action)),
sliderInput("quantile", "Quantile Range:",
min = 75, max = 95, value = c(85), step = 5
)
))
})
# reprex ----
s_75 <- function(var) box_75_test(var)
s_80 <- function(var) box_80_test(var)
s_85 <- function(var) box_85_test(var)
s_90 <- function(var) box_90_test(var)
s_95 <- function(var) box_95_test(var)
fn <- reactive(get(paste0("s_", input$quantile)))
output$plot <- renderPlot(fn()(input$variable), height = 800, width = 800)
# ^^^ note the reactive value goes fn()(var)
}
shinyApp(ui, server)
The problem I was having was due to calling the source code which was also dependent on the creation of the data frame that could only be built after a csv file was uploaded. Initially, I was only able to create a data frame as an object after the shiny session had ended but I was able to fix this by wrapping my source files and functions in an observeEvent handler like this:
observeEvent(input$file1, {
req(df_x)
source("db_prep.R")
# reprex ----
s_75 <- function(var) box_75(var)
s_80 <- function(var) box_80(var)
s_85 <- function(var) box_85(var)
s_90 <- function(var) box_90(var)
s_95 <- function(var) box_95(var)
fn <- reactive(get(paste0("s_", input$quantile)))
output$plot <- renderPlot(fn()(input$variable), height = 800, width = 800)
There is probably a more elegant way to achieve this but hey it works.

How to Convert Column into Character Type in Shiny App?

I am new to working on Shiny Apps, and relatively new to R in general. In my Shiny App, the data that is uploaded will always have a close_notes column. How can I convert this column into a string before applying the regular expression that I have (and before uppercasing it completely)? My Shiny App is below.
library(shiny)
library(dplyr) # alternatively, this also loads %>%
library(shinyWidgets)
regex_to_apply <- "\\bMASTER DATA\\b|\\bSOURCE LIST\\b|\\bVALIDITY DATES\\b|\\bMRP CONTROLLER\\b|\\bPSV\\b|\\bELIGIBILITY\\b|\\bCOST\\b|\\bMARKETING EXCLUSION\\b|\\bEFFECTIVITY\\b|\\bMISSING\\b|\bbBLANK\\b"
ui <- fluidPage(
#text with project name and my information
# use a gradient in background, setting background color to blue
setBackgroundColor(
#https://rdrr.io/cran/shinyWidgets/man/setBackgroundColor.html used this website for help on background color
color = c("#F7FBFF", "#2171B5"),
gradient = "radial",
direction = c("top", "left")
),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
tags$hr(),
checkboxInput("header", "Header", TRUE),
# Button
downloadButton("downloadData", "Download"),
actionButton('apply_regex', 'Apply Regex')
),
mainPanel(
dataTableOutput("contents")
)
)
)
server <- function(input, output) {
rv <- reactiveValues()
observe({
req(input$file1)
# input$file1 will be NULL initially. After the user selects
# and uploads a file, it will be a data frame with 'name',
# 'size', 'type', and 'datapath' columns. The 'datapath'
# column will contain the local filenames where the data can
# be found.
inFile <- input$file1
if (is.null(inFile))
return(NULL)
rv$data <- read.csv(inFile$datapath, header = input$header)
})
output$contents <- renderDataTable({
rv$data
})
output$downloadData <- downloadHandler(
filename = function() {
paste("myfile",Sys.Date(), ".csv", sep = "")
},
content = function(file) {
write.csv(rv$data, file, row.names = FALSE)
}
)
observeEvent(input$apply_regex, {
rv$data <- rv$data %>%filter(grepl(regex_to_apply, toupper(close_notes)))
})
}
shinyApp(ui, server)
What gdevaux recommended worked on my machine. I also got the following to work. You would need to add library(dplyr) if you haven't already (I see that you do have that at the top, my bad).
observeEvent(input$apply_regex, {
rv$data <- rv$data %>%
mutate(close_notes = close_notes %>% as.character() %>% toupper()) %>%
filter(grepl(regex_to_apply, close_notes))
})
Basically just mutate the column before putting it in the filter.
Summarizing what I said in comment, to transform a column to a string you can use as.character(your_variable).
To me it changed nothing because the problem was and encoding issue. I juste added encoding = "UTF-8" when loading the CSV file.
rv$data <- read.csv(inFile$datapath, header = input$header, encoding = "UTF-8")
You can also add a what #avery robbins suggested, it can save you sometimes when R automatically load strings as factors.

Shiny app runs when code submitted in console but not when Run App button is selected

I'm building a shiny app and I'm noticing that when I submit the code to console everything loads correctly and runs as expected; however when I render the app with the Run App button I'm getting errors.
Specifically, when I use the Run App button I get the following error in the application:'Error: cannot open the connection.' Additionally, I'm getting this error in the console: 'Error: cannot open the connection,' while the console reads: 'Warning in gzfile(file, "rb") :cannot open compressed file 'DATA//grm_mod.rds', probable reason 'No such file or directory''
The application is straightforward: A user uploads a data file, while on the back end an R model object is loaded, scores are estimated from the model, and results display in a table that the user can download.
What is the likely cause of this error? Note, the likely source of the error is under the code comment "Conversion steps" in the server logic.
Thank you.
# load packages
if(!require("pacman"))install.packages("pacman")
p_load(dplyr, shiny, shinythemes, mirt)
# Define UI for data upload app ----
ui <- fluidPage(
# Set theme ----
theme = shinytheme("superhero"),
# App title ----
titlePanel("Raw Score to MAP Score Conversion"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Horizontal line ----
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"'),
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(Head = "head",
All = "all"),
selected = "head")
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
tableOutput("contents"),
# Download button
downloadButton('downloadData', 'Download')
)
)
)
# Define server logic to read selected file ----
server <- function(input, output) {
output$contents <- renderTable(striped = TRUE,
{
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
# Conversion steps ----
# import the model object
mod <- readRDS('DATA//grm_mod.rds')
# generate scores
df <- data.frame(fscores(obj = mod, type = 'MAP', response.pattern = df))
# transform scores
x10_50 <- function(x) {
10 * x + 50
}
df <-
df %>%
mutate_at(vars(matches("^F.$")), .funs = list(T = ~x10_50(.)))
# add download handler
output$downloadData <- downloadHandler(
filename = function() { paste(input$file1, '.csv', sep='') },
content = function(file) {
write.csv(df, file, row.names = FALSE)
}
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
if(input$disp == "head") {
return(head(df))
}
else {
return(df)
}
# download
output$downloadData <- downloadHandler(
filename = function() {
paste('data-', Sys.Date(), '.csv', sep='')
},
content = function(file) {
write.csv(data, file)
}
)
})
}
# Create Shiny app ----
shinyApp(ui, server)
The filepath is relative to the Shiny App, not your working directory, so when you use runApp() and call readRDS('DATA//grm_mod.rds') it expects a directory DATA that is a subdirectory of the directory in which the .R file that contains your app is stored. If you move DATA to the same directory as app.r it should work.

R + Shiny : Save Uploaded Dataset to List/ choose from list item to view

i've looked all over the internet and tried multiple solution but none of them seems to be working.
In short this is my problem: I created a shiny app where the user can upload csv files and save them in a dataset. Now i want to save each uploaded dataset in a list which would help me via a selectInput button to choose which dataset to view this is the code i wrote so far :
server <- function(input, output) {
datasetlist <- list()
output$contents <- renderTable({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
input$update
tryCatch({
df <- read.csv(
input$file1$datapath,
header = isolate(input$header),
sep = isolate(input$sep),
dec = isolate(input$dec),
quote = isolate(input$quote)
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
})
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
if (isolate(input$disp == "head")) {
return(head(df))
}
else {
return(df)
}
})
output$manage <- renderUI({
selectInput("dataset", "Dataset", choices = datasetlist[], selected = datasetlist[1])
})
}
Bonus point : i would be glad if someone were also to point how to deleter records from the list without affection the whole list
EDIT 1: following the answer i received earlier here's the complete code now, the problem is that i can't seem to find a way to display the tables of the datasets
#
# 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(shinydashboard)
library(shinythemes)
library(shinyFiles)
options(shiny.maxRequestSize = 30 * 1024 ^ 2)
# Define UI for application
ui <- fluidPage(#theme= shinytheme("paper"),
# Application title
navbarPage(
"Title",
# Sidebar with input
tabPanel("Data Manager",
sidebarLayout(
sidebarPanel(
uiOutput("manage"),
fileInput(
"file1",
"Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
# Horizontal line ----
tags$hr(),
fluidRow(
# Input: Checkbox if file has header ----
column(4 ,checkboxInput("header", "Header", TRUE)),
# Input: Select number of rows to display ----
column(8, radioButtons(
"disp",
"Display",
choices = c(Head = "head",
All = "all"),
selected = "head",
inline = TRUE
))),
fluidRow(# Input: Select separator ----
column(
4, selectInput(
"sep",
"Separator",
choices = c(
Comma = ",",
Semicolon = ";",
Tab = "\t"
),
selected = ";"
)
),
# Input: Select decimals ----
column(
4 , selectInput(
"dec",
"Decimal",
choices = c("Comma" = ",",
"Period" = '.'),
selected = ','
)
)),
# Input: Select quotes ----
fluidRow(column(8 , selectInput(
"quote",
"Quote",
choices = c(
None = "",
"Double Quote" = '"',
"Single Quote" = "'"
),
selected = '"'
))),
# Horizontal line ----
tags$hr(),
actionButton("update", "Update")
),
mainPanel(fluidRow(tableOutput("contents")))
))
))
# Define server logic
server <- function(input, output, session) {
rv <- reactiveValues(
datasetlist = list()
)
observe({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
input$update
tryCatch({
df <- read.csv(
input$file1$datapath,
header = isolate(input$header),
sep = isolate(input$sep),
dec = isolate(input$dec),
quote = isolate(input$quote)
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
})
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
isolate(
rv$datasetlist <- c(rv$datasetlist,list(df))
)
})
observe({
updateSelectInput(
session = session,
inputId = "selected_dataset",
choices = 1:length(rv$datasetlist),
selected = input$selected_dataset
)
})
output$contents <- renderTable({
req(length(rv$datasetlist) >= input$selected_dataset)
df <- rv$datasetlist[[input$selected_dataset]]
if (isolate(input$disp == "head")) {
return(head(df))
}
else {
return(df)
}
})
output$manage <- renderUI({
tagList(
selectInput("selected_dataset", "Dataset", choices = '', selected = 1)
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Copy the uploaded files by user to a folder say Selected_Files using file.copy(), then use eventReactive() to read all the files in the folder to a list say datasetlist. Name the elements of the datasetlist to the file names. You can use this list reactive context in renderUI/renderTable using datasetlist().
I have written the code below which might solve your purpose.Further note read.csv has sep argument which takes care of different separators. I used radioButtons for user to provide file separators.
Edit: To capture the file format of all the uploaded files correctly I created a list df capturing the user input file formats and saving it as an R Object File_Format.rds in the working directory. Then use readRDS to load the saved list as old_df and append it to current df.
Edit2: I figured that when same file is uploaded with different parameters the name of the list File_Format remains identical hence the first element of the duplicate gets selected. I fixed this issue by prefixing the count of upload as an index to the names. Further, at the beginning of the code I added two statements to delete the RDS file and all the files in the folder Selected_Files. Hence whenever the application is opened these files are deleted first and then the interactive session follows.
Updated code is below
library(shiny)
if (file.exists("File_Format.rds")) file.remove("File_Format.rds")
do.call(file.remove, list(list.files("Selected_Files", full.names = TRUE)))
ui <- fluidPage(
# tableOutput("contents"),
sidebarPanel(
fileInput("file1", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Horizontal line ----
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Comma = ",",
Semicolon = ";",
Tab = "\t"),
selected = ","),
# Input: Select quotes ----
radioButtons("quote", "Quote",
choices = c(None = "",
"Double Quote" = '"',
"Single Quote" = "'"),
selected = '"'),
# Horizontal line ----
tags$hr(),
# Upload Button
actionButton("uploadId", "Upload")
),
# Main panel for displaying outputs ----
mainPanel(
# # Output: Data file ----
uiOutput("manage"),
# Input: Select number of rows to display ----
uiOutput("select"),
# Display Button
actionButton("displayid", "Display"),
tableOutput("contents")
)
)
########### Server ###########
server <- function(input, output, session) {
# Copy uploaded files to local folder
observeEvent(input$uploadId,{
if (is.null(input$file1) ) { return(NULL) }
file.copy(from = input$file1$datapath, to = paste0('Selected_Files/',input$file1$name ) )
df <- list(file = input$file1$name , header= input$header,
sep = input$sep,dec = input$dec,
quote = input$quote,
index = input$uploadId)
if(input$uploadId > 1){
old_df <- readRDS("File_Format.rds")
df <- sapply(names(old_df),function(n){c(old_df[[n]],df[[n]])},simplify=FALSE)
}
saveRDS(df, "File_Format.rds")
})
# Load all the uplaoded files to a list
datasetlist <- eventReactive(input$uploadId,{
# Selected_Files <- list.files("Selected_Files/")
File_Format <- readRDS("File_Format.rds")
datalist <- list()
datalist <- lapply(1:length(File_Format[[1]]), function(d) read.csv(paste0("Selected_Files/",File_Format$file[d] ),
header = File_Format$header[d],
sep = File_Format$sep[d],
dec = File_Format$dec[d],
quote = File_Format$quote[d]))
names(datalist) <- paste(File_Format$index, File_Format$file,sep = ". ")
return(datalist)
})
output$manage <- renderUI({
data <- datasetlist()
selectInput("dataset", "Dataset", choices = names(data), selected = names(data))
})
output$select <- renderUI({
data <- datasetlist()
radioButtons("disp", "Display", choices = c(Head = "head",All = "all"),
selected = "head")
})
# Display Selected File
observeEvent(input$displayid, {
output$contents <- renderTable({
data <- datasetlist()
sub_df <- data[[paste0(input$dataset)]]
if (isolate(input$disp == "head")) {
return(head(sub_df))
}
else {
return(sub_df)
}
})
})
}
shinyApp(ui, server)
Hope this was helpful.
Something like this should do it. I haven't tested it since you only supplied half of your code and I am to lazy at the moment to build my own ui file.
server <- function(input, output) {
rv <- reactiveValues(
datasetlist = list()
)
observe({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$file1)
input$update
tryCatch({
df <- read.csv(
input$file1$datapath,
header = isolate(input$header),
sep = isolate(input$sep),
dec = isolate(input$dec),
quote = isolate(input$quote)
)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
})
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
isolate(
rv$datasetlist = c(rv$datasetlist,list(df))
)
})
observe({
updateSelectInput(
session = session,
inputId = "selected_dataset",
choices = 1:length(rv$datasetlist),
selected = input$selected_dataset
)
})
output$contents <- renderTable({
req(length(rv$datasetlist) >= input$selected_dataset)
df <- rv$datasetlist[[input$selected_dataset]]
if (isolate(input$disp == "head")) {
return(head(df))
}
else {
return(df)
}
})
output$manage <- renderUI({
tagList(
selectInput("selected_dataset", "Dataset", choices = 1, selected = 1)
)
})
}
you might have to add some as.numeric() around the input$selected_dataset since selectInput normally returns a string and not a numeric.
Hope this helps!!

Read a Data Frame into a Separate Function from Shiny

I have a Shiny application which lets a user upload a CSV to undertake sentiment analysis.
The Aim:
I want to use Shiny to upload the CSV and then use a separate function (CapSent) to do the analysis and output the results.
Basically I am trying to pass the 'df' uploaded by the user into the function 'CapSent' (which resides in global.R) from Shiny. CapSent undertakes Sentiment analysis using a custom dictionary of words.
My Code So Far:
So far I have:
ui:
library(shiny)
source('global.R')
ui <- fluidPage(
sidebarPanel(
# Input: Select a file ----
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv"))
))
Server:
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
CapSent(0.1, df) # 0.1 represents a threashold, df is the data
})
}
shinyApp(ui, server)
Functions.R:
CapSent <- function(0.1, df){
newdf<-data.frame(df,stringsAsFactors = FALSE)
#....Do some sentiment analysis here on newdf
#....Then export the sentiment analysis results
write.csv(newdf,"myResults.csv")
}
The Issue
With the above code I receive the error 'Error in Encoding<-: a character vector argument expected'.
'CapSent' works when I manually add 'df' to the Global Environment (using readr) but I want users to upload their own data to analyse. Hence the question:
Is there a way to pass df to the Global Environment from Shiny?
Any advice would be much appreciated.
Try this:
ui.R
library(shiny)
# Define UI for app that draws a histogram ----
ui <- fluidPage(
# App title ----
titlePanel("Hello Shiny!"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: ----
fileInput("file1", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
actionButton("button", "Apply function/download df"),
hr(),
uiOutput("downloadButton")
),
# Main panel for displaying outputs ----
mainPanel(
h2("ORIGINAL DATA FRAME"),
DT::dataTableOutput("contents"),
br(),
uiOutput("modify")
)
)
)
server.R
server <- function(input, output) {
temp_df <- reactiveValues(df_data = NULL)
temp_df2 <- reactiveValues(df_data = NULL)
output$contents <- DT::renderDataTable({
req(input$file1)
temp_df$df_data <- read.csv(input$file1$datapath, sep = ";")
temp_df$df_data
}, options = (list(pageLength = 5, scrollX = TRUE)))
output$contents2 <- DT::renderDataTable({
temp_df2$df_data
}, options = (list(pageLength = 5, scrollX = TRUE)))
observeEvent(input$button,{
if(!is.null(temp_df$df_data)){
temp_df2$df_data <- CapSent(temp = 0.7, temp_df$df_data)
output$modify <- renderUI({
tagList(
h2("MODIFY DATA FRAME"),
DT::dataTableOutput("contents2")
)
})
output$downloadButton <- renderUI({
downloadButton("downloadData", "Download")
})
}else{
showNotification("No data was upload")
}
})
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(temp_df2$df_data, file)
})
}
as I do not know which CapSent end-use I made CapSent a function that adds a new column in the original data frame;
global.R
CapSent <- function(temp = 0.1, df){
newdf <- df
newdf$New_Col <- temp
return(newdf)
#....Do some sentiment analysis here on newdf
#....Then export the sentiment analysis results
#write.csv(newdf,"myResults.csv")
}
If you want to create a global function/variable just make a global.R which will let you use the function/variable everywhere on the ui.R or server.R.
This is the link to learn more: https://shiny.rstudio.com/articles/scoping.html
Edit: If you want to show the CSV, first of all you need to make a tabpanel and then make a table using the csv data like:
Use the package DT, install.packages("DT), is a package to make dynamic tables.
`output$yourtabpanelid = DT::renderDataTable({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
return(df)
})`
Then don't make a functions.R, just put the function below the one and put the read.csv(.....) before the function to use it in all functions at server.R like:
`df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote
)
server <- function(input, output, session) {`
And you can quit the df <- read.csv.... of the function DT but keep the return(df)

Resources