Shiny app that transfer files - shiny

I am trying to make a very simple app that transfers a user selected file to a fixed location. Then prints the results of the transfer (True / False). The syntax for copying is working outside of shiny
library(shiny)
ui <- fluidPage(
fileInput('file1', 'Choose 1st File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.fastq' , '.fasta')) ,
renderText('result')
)
server <- function(input , output){
output$result <- renderPrint({
file.copy(from = input$file1$datapath,
to = 'H:/Shiny/FileTransfer/TestLocation',
recursive = FALSE,
copy.mode = TRUE)
})
}
shinyApp(ui = ui , server = server)

There are 2 problems with your code. 1) The renderPrint function is never executed, use verbatimTextOutput instead. 2) The file name in $datapath is different from the original file, you should indicate the original name that is in $name, otherwise the destination file will have a name like 0 or some random number.
Below is your code modified with some extra information that could be useful for you. The function file.path is used to indicate the destination directory in addition with the original file name.
library(shiny)
ui <- fluidPage(
fileInput('file1', 'Choose 1st File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.fastq' , '.fasta')) ,
verbatimTextOutput('result')
)
server <- function(input , output){
destDir <- 'H:/Shiny/FileTransfer/TestLocation'
output$result <- renderPrint({
inFile <- input$file1
if (is.null(inFile)) {
cat("NOT FILE\n")
return(FALSE)
}
cat("Reading file:", inFile$name, "\n")
cat("size:", inFile$size, " Bytes, type:", inFile$type, "\n")
if (dir.exists(destDir)){
cat("Copying file to:", destDir,"\n")
result <- file.copy( inFile$datapath,
file.path(destDir, inFile$name) )
} else {
result <- FALSE
}
result
})
}
shinyApp(ui = ui , server = server)

Related

Shiny - download markdown file

library(shiny)
library(ggplot2)
report.Rmd
date: "2023-01-15"
output: html_document
params:
x_column: "Sepal.Width"
y_column: "Sepal.Length"
library(ggplot2)
ggplot(data = iris)+
aes_string(params$x_column,params$y_column)+
geom_point()
shiny app
library(shiny)
library(ggplot)
library(rmarkdown)
ui <- fluidPage(
titlePanel("Iris Data"),
sidebarLayout(
sidebarPanel(
selectizeInput("xcol",
"Choose X Axis",
choices = names(iris)
),
selectizeInput("ycol",
"Choose Y Axis",
choices = names(iris)
),
downloadButton("project", "Download plot")
),
mainPanel(
plotOutput("plot")
)
)
)
server <- function(input, output) {
filename = "report.html
output$plot <- renderPlot({
ggplot(data=iris)+
aes_string(x=input$xcol, y=input$ycol)+
geom_point()
})
output$print <- downloadHandler({
filename="report.html"
content = function(file) {
rmarkdown::render("report.Rmd",
output_file=file, params=list(x_column = input$xcol,
y_column = input$ycol))
}
})
}
I can't get the app to render my rmarkdown file. I can't seem to see the mistake. report.Rmd is in my working directory. I can get it to work outside of shiny, but in shiny it says there is an error and the content is missing without a default value
There are two issues with your code. First, you used the id Project for the downloadButton but named the output print. Second, the API of downloadHandler is a bit different from reactive or renderXXX, i.e. you have to pass filename and content as arguments.
Note: Also it's good practice to copy the report file to a temporary directory before processing it and to evaluate the document in a child of the global environment. See Generating downloadable reports. As an example where missing the last step fails to render an Rmd correctly see this post. Finally, note that aes_string is deprecated since ggplot2 3.4.0. Instead it's recommended to use the .data pro-noun as I do in the code below.
library(shiny)
library(ggplot2)
ui <- fluidPage(
titlePanel("Iris Data"),
sidebarLayout(
sidebarPanel(
selectizeInput("xcol",
"Choose X Axis",
choices = names(iris)
),
selectizeInput("ycol",
"Choose Y Axis",
choices = names(iris)
),
downloadButton("print", "Download plot")
),
mainPanel(
plotOutput("plot")
)
)
)
server <- function(input, output) {
output$plot <- renderPlot({
ggplot(data = iris) +
aes(.data[[params$x_column]], .data[[params$y_column]]) +
geom_point()
})
output$print <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
rmarkdown::render(tempReport,
output_file = file,
params = list(
x_column = input$xcol,
y_column = input$ycol
),
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui, server)
#>
#> Listening on http://127.0.0.1:5776
#> Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
#> ℹ Please use tidy evaluation ideoms with `aes()`

R Shiny -- Error in readLines: 'con' is not a connection

I am trying to run the following code, but keep getting this error:
Error in readLines: 'con' is not a connection
The following is my program:
library(shiny)
library(shinyFiles)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
width = 2,
fileInput("file1", "Choose the first HTML File", accept = ".html")
),
mainPanel(
p("File Name"),
verbatimTextOutput("file_name"),
htmlOutput(outputId = 'result')
)
)
)
server <- function(input, output) {
file <- reactive({input$file1})
req(file)
if(is.null( reactive(input$file1$datapath))) return(NULL)
rawHTML <- reactive(paste(readLines(input$file1$datapath), collapse="\n"))
output$file_name <- renderText({
print(rawHTML)
})
output$result <- renderUI({
getPage<-function() {
return(includeHTML( input$file1$datapath))
}
output$inc<-renderUI({getPage()})
})
}
runApp(list(ui = ui, server = server), launch.browser =T)
I want to read the html code from an external file, and save the code as a string. Is there a solution for this?

Is there a good way to merge data based on a drop down menu in R?

I have been trying to merge data with another data set based on input from a drop down. I have just started learning R and have run into some problems and want to know if there is a better way of going about this.
I am getting an error that it cannot coerce class c(ReactiveExpr, reactive) to a data frame.
library(shiny)
library(plyr)
library(dplyr)
library(xlsx)
server <- function(input, output){
annotation1 <- read.xlsx("input1.xlsx", sheetIndex = 1, header = TRUE)
annotation2 <- read.xlsx("input2.xlsx", sheetIndex = 1, header = TRUE)
data_input <- eventReactive(input$userfile, {
df <- read.xlsx(input$userfile$datapath, sheetIndex = 1, header = TRUE)
})
output$data_input <- renderTable(data_input())
output$annotation <- renderTable(annotation)
data_species <- c("Set1", "Set2")
# Drop-down selection box for which data set
output$choose_species <- renderUI ({
selectInput("species", "Species", as.list(data_species))
})
output$mergeddata <- renderTable({
if(input$species == "Set1"){
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))
}
else if(input$species == "Set2"){
eventReactive("Set2",({left_join(data_input(), annotation2, by = c("Column1" = "Column1"))}))
}
})
}
ui <- fluidPage(
titlePanel(
div("Test")
),
sidebarLayout(
sidebarPanel(
fileInput("userfile", "Input File", multiple =FALSE,
buttonLabel = "Browse Files", placeholder = "Select File"),
uiOutput("choose_species"),
uiOutput("choose_annotations"),
),
mainPanel(
tableOutput("mergeddata"),
br()
),
),
)
# Run the application
shinyApp(ui = ui, server = server)
In general, you approach seems ok. The error you get is from the line
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))
An eventReactive returns an (unevaluated) reactive expression which you try to render as data.frame with renderTable. To circumvent this, you could use:
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))()
However, here you don't need eventReactive, because your reactivity comes from input$species (you want to change the table output based on this input). Therefore, you can just use:
output$mergeddata <- renderTable({
if(input$species == "Set1"){
merge_data <- annotation1
} else {
merge_data <- annotation2
}
left_join(data_input(), merge_data, by = c("Column1"))
})

Can I call a function (not a module) from within shiny modile- can I pass the module reactive values as arguments of function

I am pretty new to Shiny modules.
I am trying to call a function (not a module) from one of my modules.
I would like to pass in the contents of my current reactive values (in my module) as arguments into the function.
The function make a sql query command based on the mrn number, startdate and enddate that is supposed to be fed into the function from 'modemtab'.
this is the error that I get:
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
I understand that this is because I'm passing the reactive values not contents of them into the function. My question is how can I pass the contents of these reactive values.
I included a piece of my code here.
Thanks.
app_server <- function(input, output,session) {
.
.
# getting csvupload_values from the first module and feeding it into the next.
csvupload_values <- callModule(csvupload, 'csv-upload')
callModule(modemtab,'mrntab', csvupload_values)
modemtab <- function(input, output, session, csvupload_values){
# the ouput$query is made in the UI part, but it's not the cause of issue.
output$query <- renderText({
if(!is.null(csvupload_values$file_uploaded())){
make_query(mrns = csvupload_values$file_uploaded()$mrns,
startDate = csvupload_values$dates()[1],
endDate = csvupload_values$dates()[2])
}
#This is the function called from within the second module (modemtab)
#this function is saved as a separate file in R folder
make_query <- function(...){
glue_sql("
select *
FROM table
WHERE
rgn_cd = {`rgn_cd`}
AND prdct_lne_cd = {`lob`}
AND ENCTR_STRT_TS >= {`startDate`}
AND ENCTR_END_TS <= {`endDate`}
"
,...
,.con = DBI::ANSI())
}
csvuploadUI <- function(id){
ns <- NS(id)
tagList(
fileInput(ns('file'), "Choose CSV File",
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
dateRangeInput(
ns('mrn_date_range'), label = 'Select the range of date:',
start = NULL, end = NULL, min = NULL,
max = NULL, format = "mm/dd/yyyy",
startview = "month", weekstart = 0,
language = "en", separator = " to ", width = NULL),
# Input: Checkbox if file has header ----
checkboxInput(ns('header'), "Header", TRUE)
)
}
# Module Server
csvupload <- function(input, output, session){
userFile <- reactive({
# If no file is selected, don't do anything
validate(need(input$file, message = FALSE))
input$file
})
dataframe <- reactive({
read.csv(userFile()$datapath,
header = input$header)
})
Here:
csvupload_values <- callModule(csvupload, 'csv-upload')
callModule(modemtab,'mrntab', csvupload_values)
csvupload_values is a reactive conductor, so you can't do callModule(modemtab,'mrntab', csvupload_values) outside of a reactive context. You can do:
server <- function(input, output,session) {
csvupload_values <- callModule(csvupload, 'csv-upload')
observeEvent(csvupload_values(),{
if(!is.null(csvupload_values())){
callModule(modemtab, 'mrntab', csvupload_values)
}
})
}
Now, csvupload_values() is a dataframe once you have uploaded the file, so I don't understand why you do csvupload_values$file_uploaded(). Here is a full example:
modemtabUI <- function(id){
ns <- NS(id)
textOutput(ns("query"))
}
modemtab <- function(input, output, session, csvupload_values){
output$query <- renderText({
colnames(csvupload_values())
})
}
csvuploadUI <- function(id){
ns <- NS(id)
tagList(
fileInput(ns('file'), "Choose CSV File",
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
checkboxInput(ns('header'), "Header", TRUE),
dateRangeInput(
ns('mrn_date_range'), label = 'Select the range of date:',
start = NULL, end = NULL, min = NULL, max = NULL, format = "mm/dd/yyyy",
startview = "month", weekstart = 0,
language = "en", separator = " to ", width = NULL)
)
}
csvupload <- function(input, output, session){
userFile <- reactive({
# If no file is selected, don't do anything
validate(need(input$file, message = FALSE))
input$file
})
reactive({
read.csv(userFile()$datapath, header = input$header)
})
}
ui <- fluidPage(
csvuploadUI("csv-upload")
modemtabUI("mrntab")
)
server <- function(input, output,session) {
csvupload_values <- callModule(csvupload, 'csv-upload')
observeEvent(csvupload_values(),{
if(!is.null(csvupload_values())){
callModule(modemtab, 'mrntab', csvupload_values)
}
})
}
shinyApp(ui, server)

Downloading the output from Shiny APP (need some advice)

I want to download the output of this App which I made but there is an error and when I open the downloaded data it is empty.I make a data set by output$other_val_show and I want to download it. Any advice?
The following code in for the UI section.
library(shiny)
library(quantreg)
library(quantregGrowth)
library(plotly)
library(rsconnect)
library(ggplot2)
library(lattice)
ui = tagList(
tags$head(tags$style(HTML("body{ background: aliceblue; }"))),
navbarPage(title="",
tabPanel("Data Import",
sidebarLayout(sidebarPanel( fileInput("file","Upload your CSV",multiple = FALSE),
tags$hr(),
h5(helpText("Select the read.table parameters below")),
checkboxInput(inputId = 'header', label = 'Header', value = FALSE),
checkboxInput(inputId = "stringAsFactors", "StringAsFactors", FALSE),
radioButtons (inputId = 'sep', label = 'Separator',
choices = c(Comma=',',Semicolon=';',Tab='\t', Space=''), selected = ',')
),
mainPanel(uiOutput("tb1"))
)),
tabPanel("Interval",
sidebarLayout(sidebarPanel(
uiOutput("model_select"),
uiOutput("var1_select"),
uiOutput("rest_var_select"),
#uiOutput("testText1"), br(),
#textInput("Smooting Parameter min value", "Smooting Parameter max value", value = "")
sliderInput("range", "Smooth Parameter range:",min = 0, max = 1000, value = c(0,100)),
downloadButton('downloadData', 'Download')
),
mainPanel(helpText("Selected variables and Fitted values"),
verbatimTextOutput("other_val_show")))),
tabPanel("Model Summary", verbatimTextOutput("summary")),
tabPanel("Scatterplot", plotOutput("scatterplot"))#, # Plot
#tabPanel("Distribution", # Plots of distributions
#fluidRow(
#column(6, plotOutput("distribution1")),
#column(6, plotOutput("distribution2")))
#)
,inverse = TRUE,position="static-top",theme ="bootstrap.css"))
The following code in for the Server section. (I want to download the output which is "gr" and I want to download it by downloadHandler function.
server<-function(input,output) {
data <- reactive({
lower <- input$range[1]
upper <- input$range[2]
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=input$sep, header = input$header, stringsAsFactors = input$stringAsFactors)
})
output$table <- renderTable({
if(is.null(data())){return ()}
data()
})
output$tb1 <- renderUI({
tableOutput("table")
})
#output$model_select<-renderUI({
#selectInput("modelselect","Select Algo",choices = c("Reference Interval"="Model"))
#})
output$var1_select<-renderUI({
selectInput("ind_var_select","Select Independent Variable", choices =as.list(names(data())),multiple = FALSE)
})
output$rest_var_select<-renderUI({
checkboxGroupInput("other_var_select","Select Dependent Variable",choices =as.list(names(data()))) #Select other Var
})
output$other_val_show<-renderPrint({
input$other_var_select
input$ind_var_select
f<-data()
lower <- input$range[1]
upper <- input$range[2]
library(caret)
library(quantregGrowth)
dep_vars <- paste0(input$ind_var_select, collapse = "+")
after_tilde <- paste0("ps(", dep_vars, ", lambda = seq(",lower,",",upper,",l=100))")
dyn_string <- paste0(input$other_var_select, " ~ ", after_tilde)
Model<-quantregGrowth::gcrq(as.formula(dyn_string),tau=c(0.025,0.975), data=f)
temp <- data.frame(Model$fitted)
gr <- cbind(f, temp)
print(gr)
})
output$downloadData <- downloadHandler(
write.csv(gr, file, row.names = FALSE)
)
}
shinyApp(ui=ui,server=server)
It's hard to fully answer this without a minimal reproducibile example, but here's what I would try:
Create gr outside of renderPrint
Use gr() in downloadHandler
Rewrite downloadHandler to include content and filename arguments
Here's a minimal example with the same logic as your app, i.e. create a reactive dataframe which is both printed (renderPrint) and downloadable (downloadHandler).
library(shiny)
ui <- navbarPage(title = "Example",
tabPanel("First",
selectInput("fruit", "Fruit", c("apple", "orange", "pear")),
h4("Output from renderPrint:"),
textOutput("other_val_show"),
h4("Download Button: "),
downloadButton("downloadData")))
server <- function(input, output) {
gr <- reactive({
data.frame(fruit = input$fruit)
})
output$other_val_show <- renderPrint({
print(gr())
})
output$downloadData <- downloadHandler(
filename = "example.csv",
content = function(file) {
write.csv(gr(), file)
})
}
shinyApp(ui, server)
You define gr inside the scope of that renderPrint function so it isn't available to downloadHandler. You should define gr as a reactive value somewhere outside that function. That way, when you assign it in the renderPrint function, it will be accessible to the entire scope of your program.
In the future, it would be helpful to provide the text of any error messages you get - they are often quite helpful to solving problems.