shiny cannot save upload file in local disk - r

I want shiny to upload and save data in the local disk, everything works fine except the saving part, below is the code, any help?
PS: There is no error message.
library(shiny)
library(tidyverse)
library(DT)
responsesDir <- file.path("c:/Users/Administrator/Desktop/11") #save at this dir
ui = fluidPage(
fileInput("FileInput", "File select"),
DT::dataTableOutput("table")
)
server = function(input, output, session) {
datasetInput <- eventReactive(input$FileInput, {
infile <- input$FileInput
read.csv(infile$datapath, header = TRUE)
})
data_save <- eventReactive(
input$FileInput,
{write.csv(datasetInput(), file = paste0(responsesDir, '/iris_set.csv'),
row.names = FALSE, quote = TRUE)}) #name iris_set.csv for example
output$table = DT::renderDataTable(datasetInput())
}
shinyApp(ui, server)

Finally after googling for couple of hours, I figured out by myself. Replacing the eventReactive from data_save line to observeEvent it worked.
library(shiny)
library(tidyverse)
library(DT)
responsesDir <- file.path("c:/Users/Vincent/Desktop/ls") #save at this dir
ui = fluidPage(
fileInput("FileInput", "File select"),
DT::dataTableOutput("table")
)
server = function(input, output, session) {
datasetInput <- eventReactive(input$FileInput, {
infile <- input$FileInput
read.csv(infile$datapath, header = TRUE)
})
data_save <- observeEvent(
input$FileInput,
{write.csv(datasetInput(), file = paste0(responsesDir, '/fuck_you.csv'),
row.names = FALSE, quote = TRUE)}) #name iris_set.csv for example
output$table = DT::renderDataTable(datasetInput())
}
shinyApp(ui, server)

Related

Multiple UI Output Based on File Upload Using Shiny Modules

Dataset Viewer
Hello, I am attempting to create a shiny application that allows to user to view their uploaded datasets individually.
When there is no file uploaded a message appears asking the user to upload their file...once a csv file is uploaded, the message disappears and shows the users uploaded datasets.
What I've tried
I've tried: using conditionalPanels in app.R & upload.R, creating a separate R file exclusively for each ui condition. I believe my issue is that output$table (function that renders mainpanel ui) is not being triggered after the file uploads.
My issue
Once the user uploads a csv file(any readable csv file), the pre-existing message is not being replaced by the uploaded datasets.
upload.R
data = list()
numDatasets = 0
uploadSideUI <- function(id) {
ns <- NS(id)
tagList(
h2("Dataset Viewer"),
fileInput(ns("file"),label = "Upload File", multiple = FALSE, accept = ".csv")
)
}
uploadMainUI <- function(id) {
ns <- NS(id)
uiOutput(ns("table"))
}
uploadServer <- function(id) {
moduleServer(id, function(input,output,session){
observeEvent(eventExpr = input$file,
handlerExpr = {
df <- read.csv(file = input$file$datapath,header = FALSE)
data <<- c(data,list(df))
numDatasets <<- numDatasets + 1
})
output$table <- renderUI({
if(numDatasets ==0){
h2("please upload file")
}else{
req(input$file)
print(numDatasets)
lapply(1:numDatasets,function(i) {
dataframe = data[[i]]
tagList(
h2(paste("dataset",i)),
hr(),
datatable(dataframe,rownames = FALSE, option = list(scrollY="300px",searching=FALSE)),
br()
)
})
}
})
})
}
app.R
#app.R
library(DT)
library(shiny)
source("testModule.R")
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
uploadSideUI("uploadPage")
),mainPanel(
uploadMainUI("uploadPage")
)
)
)
server <- function(input, output, session) {
uploadServer("uploadPage")
}
shinyApp(ui = ui, server = server)
I am new to the modulization process in shiny, so if you have any other suggestions please point them out! Thanks in advance!
Try this
uploadServer <- function(id) {
moduleServer(id, function(input,output,session){
rv <- reactiveValues(numDatasets = 0)
observeEvent(eventExpr = input$file,
handlerExpr = {
df <- read.csv(file = input$file$datapath,header = FALSE)
data <<- c(data,list(df))
rv$numDatasets <<- rv$numDatasets + 1
})
output$table <- renderUI({
if(rv$numDatasets == 0){
h2("please upload file")
}else{
req(input$file)
print(rv$numDatasets)
lapply(1:rv$numDatasets,function(i) {
dataframe = data[[i]]
tagList(
h2(paste("dataset",i)),
hr(),
datatable(dataframe,rownames = FALSE, option = list(scrollY="300px",searching=FALSE)),
br()
)
})
}
})
})
}

How to render a plot from a list of multiple objects on ShinyApp

I have a function Identify_IP() that returns a list of 1- dataframe
2-ggplot. I need to renderTable and renderPlot in ShinyApp. This shinyApp code renders only the dataframe. But I can't render the plot. Any help?
library(shiny)
source('InflectionP2.R', local = TRUE)
runApp(
list(
ui = fluidPage(
titlePanel("Upload your file"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xls file',
accept = c(".XLS")),
actionButton("btn", "Update Table"),
actionButton("btn1", "Display Plot"),
downloadButton('downloadData', 'Download')
),
mainPanel(
tableOutput('what'),
plotOutput('pl'))
)
)
,
server = function(input, output, session){
dataOP <- reactive({
inFile <- input$file1
if (is.null(input$file1))
return(NULL)
Identify_IP(read.table(inFile$datapath))
list(tble = df1, txt = inflection_points, plt = p )
})
observeEvent(input$btn, output$what <- renderTable({dataOP()$tble}))
observeEvent(input$btn1, output$pl <- renderPlot({
plot(dataOP()$plt)
}))
}
))
Using the following server worked for me:
server = function(input, output, session){
dataOP <- reactive({
inFile <- input$file1
if(is.null(input$file1)){
return(NULL)
}
#Identify_IP(read.table(inFile$datapath))
list(tble = c(1:20), txt = c(1:10), plt = rnorm(100))
})
observeEvent(input$btn,{
output$what <- renderTable({
dataOP()$tble
})
})
observeEvent(input$btn1,{
output$pl <- renderPlot({
plot(dataOP()$plt)
})
})
}
Note that I commented out your function Identify_IP and replaced the results with arbitrary values.
If this still doesn't work your problem probably is probably related to this function or with the values returned by the function, respectively.

Using an .xlsx file as an input in a Shiny App

I am working on a shiny app that requires a Excel with multiple sheets as an input. It was working well with the xlsx library and read.xlsx function. However, it returns the following error:
java.lang.IllegalArgumentException: Cell index must be >= 0
I've now switched to gdata and read.xls, but I get a file path error every time I run the model.
I wonder if anyone dealt with this problem before and if there are any simple solutions to fix this problem.
EDIT:
The following code
library(shiny)
library(xlsx)
ui <- fluidPage(
fileInput("uploadFile", "XLSX file"),
verbatimTextOutput("summary")
)
server <- function(input, output) ({
dataset<-reactive({
inFile <- input$uploadFile
dat<-read.xlsx(inFile$datapath, 1)
return(dat)
})
output$summary <- renderText({summary(dataset())})
})
shinyApp(ui, server)
Returns:
Error : package ‘rJava’ could not be loaded
If, instead I use
library(shiny)
library(readxl)
ui <- fluidPage(
fileInput("uploadFile", "XLSX file"),
verbatimTextOutput("summary")
)
server <- function(input, output) ({
dataset<-reactive({
inFile <- input$uploadFile
dat<-read_excel(inFile$datapath, sheet = 1)
return(dat)
})
output$summary <- renderText({summary(dataset())})
})
shinyApp(ui, server)
I get:
Error: Missing file extension.
(Using readxl)
The datapath column from input$uploadFile is a path to a temp file which has no extension. So read_excel() does not know what format it is.
Use read_xlsx() instead:
dat <- read_xlsx(inFile$datapath, sheet = 1)
I just tried this and it worked fine for me.
library(shiny)
library(readxl)
runApp(
list(
ui = fluidPage(
titlePanel("Use readxl"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")
)
),
mainPanel(
tableOutput('contents'))
)
),
server = function(input, output){
output$contents <- renderTable({
inFile <- input$file1
if(is.null(inFile))
return(NULL)
file.rename(inFile$datapath,
paste(inFile$datapath, ".xlsx", sep=""))
read_excel(paste(inFile$datapath, ".xlsx", sep=""), 1)
})
}
)
)
Also, see this.
https://shiny.rstudio.com/gallery/file-upload.html

r shiny - upload all files from shinyDirChoose folder to server

I saved the path of a user-defined folder with shinyDirChoose. Now I want to upload files from that user's folder, but I cannot figure out how to do it.
1) All on the server end?
2) Feeding the file paths to fileInput somehow?
This is how I construct the file paths for the three files that should be uploaded.
### ui end, to browse to desired folder
ui = fluidPage(shinyDirButton('directory', 'Folder select', 'Please select a folder'))
### extracting the folder path
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
### constructing the 3 file paths
datpat <- renderText({
req(nchar(path1())>0)
datpat <- paste0(path1(),"/data.csv")
})
vispat <- renderText({
req(nchar(path1())>0)
vispat <- paste0(path1(),"/visit.csv")
})
statpat <- renderText({
req(nchar(path1())>0)
statpat <- paste0(path1(),"/statvisit.csv")
})
So now I have these paths, but how can I use them to upload the related content to the server? A simple read.csv unfortunately does not do the trick.
EDIT - but not there yet...
Working further with the great help #SBista provided, I think I'm approaching my goal, but see below code...
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
observe({
if(!is.null(path1)){
### vis1
vis1 <- reactive({
datpat <- paste0(path1(),"/visit.csv")
vis <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
vis
})
### dataruw1
dataruw1 <- reactive({
datpat <- paste0(path1(),"/data.csv")
dataruw <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
dataruw
})
}
})
Unfortunately, dataruw1 and vis1 do not seem to be generated, as I get a 'could not find function' error when trying to use the actual data with dataruw1() and vis1(). What am I missing? Any idea? Thanks a lot in advance!
I have modified your app to demonstrate that you can use read.csv to upload the file. For demonstration I am reading only one file from the folder and displaying the read data frame in a datatable.
library(shiny)
library(shinyFiles)
### ui end, to browse to desired folder
ui = fluidPage(shinyDirButton('directory', 'Folder select', 'Please select a folder'),
tableOutput(outputId = "datpat")
)
### extracting the folder path
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
### constructing the 3 file paths
observe({
if(!is.null(path1)){
output$datpat <- renderTable({
req(nchar(path1())>0)
datpat <- paste0(path1(),"/data.csv")
dat <- read.csv(datpat)
dat
})
}
})
}
shinyApp(ui = ui, server = server)
Hope it helps!
Happy to have found a solution! Big thanks to SBista once more, even though I did it a bit differently. The below code is not just a chunk (as in my original post) but fully functional, provided you browse to a folder that contains a data.csv file.
library(shiny)
library(shinyFiles)
library(htmltools)
##############################################################################
ui = navbarPage(
HTML("Title"),
tabPanel(HTML("<font size=3>Start</font>"),
sidebarPanel(width = 2,
shinyDirButton('directory', 'Folder select', 'Please select a folder'),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator', c(Comma=',',Semicolon=';',Tab='\t'), selected=';'),
radioButtons('quote', 'Quote', c(None='','Double Quote'='"','Single Quote'="'"), selected='"')),
mainPanel(
fluidRow(
column(6, tags$b(textOutput("text")))),
tags$hr(),
fluidRow(
column(6, dataTableOutput("table"))
)
)
)
)
server = function(input, output, session) {
volumes <- getVolumes()
shinyDirChoose(input, 'directory', roots=volumes, session=session)
path1 <- reactive({
return(print(parseDirPath(volumes, input$directory)))
})
dataruw1 <- eventReactive(input$directory, {
datpat <- paste0(path1(),"/data.csv")
dataruw <- read.csv(datpat, header = input$header, sep = input$sep, quote = input$quote,
stringsAsFactors = FALSE)
dataruw
})
output$text <- renderText({
path1()
})
output$table <- renderDataTable({
dataruw1()
})
}
shinyApp(ui = ui, server = server, options = list(launch.browser=TRUE))

Downloading pdf plot using shiny app after reading excel files

As, I am new to shiny apps need some assistance, uploading excel file and generating table output in shiny app works fine, but can't able to download the plot to a pdf format
Here is my code
library(shiny)
library(openxlsx)
library(lattice)
runApp(
list(
ui = fluidPage(
titlePanel("plots"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
tags$hr(),
downloadButton('down',"download plot")
),
mainPanel(
tableOutput('contents'),
plotOutput('plot'))
)
),
server = function(input, output){
output$contents <- renderTable({
inFile <- input$file1
if(is.null(inFile))
return(NULL)
else
read.xlsx(inFile$datapath)
})
plotInput <- reactive({
df <- input$file1
xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")
})
output$plot <- renderPlot({
print(plotInput())
})
output$down <- downloadHandler(
filename = function(){paste("plot",".pdf",sep=".") },
content = function(file) {
pdf(file)
xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")
dev.off()
}
)
}
)
)
The problem was that in some parts of your code you were accessing a dynamic data frame via df() but you had never defined it.
In this kind of problem, it is best to create a reactive data frame, say, df which contains the uploaded data and is passed to other reactive parts of the code via df().
Full example:
library(shiny)
library(openxlsx)
library(lattice)
runApp(
list(
ui = fluidPage(
titlePanel("plots"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
tags$hr(),
downloadButton('down',"download plot")
),
mainPanel(
tableOutput('contents'),
plotOutput('plot'))
)
),
server = function(input, output){
df <- reactive({
inFile <- input$file1
req(inFile) # require that inFile is available (is not NULL)
# (a user has uploaded data)
# read.xlsx(inFile$datapath)
head(iris, 10)
})
output$contents <- renderTable({
# access uploaded data via df()
df()
})
plotInput <- reactive({
df <- df()
xyplot(df[,2]~df[,1], df ,xlim=c(0,10),ylim=c(0,100),type = "b")
})
output$plot <- renderPlot({
plotInput()
})
output$down <- downloadHandler(
filename = function(){paste("plot",".pdf",sep=".") },
content = function(file) {
pdf(file)
#xyplot(df[,2]~df[,1],df(),xlim=c(0,10),ylim=c(0,100),type = "b")
# you have to print the plot so that you can open pdf file
print(plotInput())
dev.off()
}
)
}
)
)

Resources