I am fairly new to Shiny Apps and I wish to download the plots as png/pdf file. After publishing the app online, the downloaded filename is correct but it is an empty file. I applied print function in content for downloadHandler but it doesn seem to work. Can anyone help me out? Thanks
ui.r
library(shiny)
ui <- fluidPage(
titlePanel("My First Shiny Project"),
sidebarLayout(
sidebarPanel(
selectInput("select","Choose a Dataset",
choices = list("trees","pressure"),
selected = "pressure"),
selectInput("format","Choose file format",
choices = list("pdf","png"))
),
mainPanel(
plotOutput("graph")
)
),
downloadButton("download","Download Here")
)
server.r
library(shiny)
server <- function(input,output){
data <- function()({
switch(input$select,
"trees" = trees,
"pressure" = pressure)
})
output$graph <- renderPlot(
plot(data())
)
output$download <- downloadHandler(
filename = function(){
paste("data",input$select,input$format,sep = ".")
},
content = function(file){
if(input$format == "png")
png(file)
if(input$format == "pdf")
pdf(file)
print(plot(data()))
dev.off
}
)
}
It seems that the only issue was that you used dev.off instead of dev.off(), you also do not need the print() statement. A working version of your code is shown below, hope this helps!
library(shiny)
library(ggplot2movies)
library(dplyr)
ui <- fluidPage(
titlePanel("My First Shiny Project"),
sidebarLayout(
sidebarPanel(
selectInput("select","Choose a Dataset",
choices = list("trees","pressure"),
selected = "pressure"),
selectInput("format","Choose file format",
choices = list("pdf","png"))
),
mainPanel(
plotOutput("graph")
)
),
downloadButton("download","Download Here")
)
server <- function(input,output){
data <- function()({
switch(input$select,
"trees" = trees,
"pressure" = pressure)
})
output$graph <- renderPlot(
plot(data())
)
output$download <- downloadHandler(
filename = function(){
paste("data",input$select,input$format,sep = ".")
},
content = function(file){
if(input$format == "png")
png(file)
if(input$format == "pdf")
pdf(file)
plot(data())
dev.off()
}
)
}
shinyApp(ui,server)
Related
Is there a practical way to download all your sidebar inputs as a pdf in a shiny app?Im trying to create a dataframe but it is not so clear and the one column name is not displayed. I use kable() but there may be a more practical way to display.
library(shiny)
server <- shinyServer(function(input, output, session) {
df<-reactive({
Report<-input$rep
Select<-input$sel
df<-as.data.frame(Report,Select)
})
output$downloadData = downloadHandler(
filename = function() {"sampleTable.pdf"},
content = function(file) {
x <- kable(
df(),
format = "latex", caption = "Prices(long)",booktabs=TRUE)%>%
kable_styling(latex_options="scale_down")
save_kable(x, file)
},
contentType = 'application/pdf'
)
})
ui_panel <-
tabPanel("Multi-Select Input Test",
sidebarLayout(
sidebarPanel(
radioButtons("rep","Choose report",c("kable","text")),
selectInput("sel","Select",c("choice1","choice2")),
downloadButton('downloadData', 'Download'),
br()
),
mainPanel(
tabsetPanel(tabPanel("Text")
)
)
))
ui <- shinyUI(navbarPage(" ",ui_panel))
runApp(list(ui=ui,server=server))
I am working on a data cleaning app. The app is supposed to take a file from the user clean it, and be able to download the cleaned data. For some reason my app will only download the html of the app and not a csv. Any Help would be awesome. Here is what I have so far.
The interface is asking me to add more details but this is all I got
ui.R
library(shiny)
library(DT)
###Allows up to 60 mgs of data
options(shiny.maxRequestSize = 60*1024^2)
navbarPage(
"Astute App",
tabPanel(
"Clean Data",
fluidRow(
fileInput('target_upload', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
radioButtons("separator","Separator: ",choices = c(";",",",":"), selected=",",inline=TRUE),
DT::dataTableOutput("sample_table")),
downloadButton("cleaned_data", label = "Download Data"),
),
tabPanel(
"Time Series Analysis",
fluidPage(
)
),
tabPanel(
"Prediction",
fluidPage(
)
),
collapsible = TRUE
)
The interface is asking me to add more details but this is all I got
server.R
library(shiny)
library(DT)
###Allows up to 60 mgs of data
options(shiny.maxRequestSize = 60*1024^2)
function(input, output, session){
########Reads in uplaoded Data
df_products_upload <- reactive({
inFile <- input$target_upload
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath, header = TRUE,sep = input$separator)
return(df)
})
######Clean the data#####
Cleaned_data <- df
download_cleaned_data <- downloadHandler(
filename = Cleaned_data,
content = function(file){
file.copy("data/", file)}
)
###Displays Uploaded data unclean
output$sample_table<- DT::renderDataTable({
df <- df_products_upload()
DT::datatable(df)
})
}
Not sure what else to add
A couple of issues in the downloadHandler section. It should look like this:
output$cleaned_data <- downloadHandler(
filename = "mydata.csv",
content = function(file) {write.csv(df_products_upload(), file)}
)
Here is a minimal working example, showing uploading and downloading a file:
library(shiny)
ui <- fluidPage(
#Select file
fileInput('myfileinput', 'Choose file to upload'),
#Download file
downloadButton("myfiledownload", label = "Download file"),
#Data table of loaded file
tableOutput("mydatatable")
)
server <- function(input, output, session) {
#Create a reactive dataframe to hold our loaded file
df_fileuploaded <- reactive({
#If no file selected set the dataframe to null and exit
if (is.null(input$myfileinput)) return(NULL)
#Load the selected file
return(read.csv(input$myfileinput$datapath))
})
#Download handler
output$myfiledownload <- downloadHandler(
filename = "mydata.csv",
content = function(file) {write.csv(df_fileuploaded(), file)}
)
#Data table
output$mydatatable <- renderTable({
df_fileuploaded()
})
}
shinyApp(ui, server)
Here is your full app with those changes:
ui.r
library(shiny)
library(DT)
###Allows up to 60 mgs of data
options(shiny.maxRequestSize = 60*1024^2)
navbarPage(
"Astute App",
tabPanel(
"Clean Data",
fluidRow(
fileInput('target_upload', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
radioButtons("separator","Separator: ",choices = c(";",",",":"), selected=",",inline=TRUE),
DT::dataTableOutput("sample_table")),
downloadButton("cleaned_data", label = "Download Data"),
),
tabPanel(
"Time Series Analysis",
fluidPage(
)
),
tabPanel(
"Prediction",
fluidPage(
)
),
collapsible = TRUE
)
server.r
library(shiny)
library(DT)
###Allows up to 60 mgs of data
options(shiny.maxRequestSize = 60*1024^2)
function(input, output, session){
########Reads in uplaoded Data
df_products_upload <- reactive({
inFile <- input$target_upload
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath, header = TRUE,sep = input$separator)
return(df)
})
output$cleaned_data <- downloadHandler(
filename = "mydata.csv",
content = function(file) {write.csv(df_products_upload(), file)}
)
###Displays Uploaded data unclean
output$sample_table<- DT::renderDataTable({
df <- df_products_upload()
DT::datatable(df)
})
}
I'm looking to make a shiny app where users upload a text file and can input the terms they want filter (so sentences that have two particular words or phrases). then they can download the results. My script so far looks like:
ui <- fluidPage(
titlePanel("Download data"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose .txt file",
multiple = F,
accept = c(".txt")),
textInput('energy_co', 'Name of energy company'),
textInput('asset', 'name of Asset Manager'),
downloadButton("downloadData", "Download")
),
mainPanel(
tableOutput("table")
)
)
)
server <- function(input, output, session) {
options(shiny.maxRequestSize=30*1024^2)
output$table <- renderTable({
req(input$file1)
data <- read_lines(input$file1$datapath)
text_df <- as_data_frame(data)
company_data <- text_df %>%
filter(str_detect(terms, input$asset)) %>%
filter(str_detect(terms, input$energy_co)) %>%
distinct(.)
company_data
})
output$downloadData <- downloadHandler(
filename = function() {
paste(company_data, ".csv", sep = "")
},
content = function(file) {
write.csv(company_data, file1, row.names = FALSE)
}
)
}
shinyApp(ui, server)
I can upload the dataset (a .txt file) but nothing happens either when I try and render the table or when I try and download the results as a csv. I think the server script might need to be reactive? any help appreciated
Try this
ui <- fluidPage(
titlePanel("Download data"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose .txt file",
multiple = F,
accept = c(".txt")),
textInput('energy_co', 'Name of energy company'),
textInput('asset', 'name of Asset Manager'),
downloadButton("downloadData", "Download")
),
mainPanel(
tableOutput("table")
)
)
)
options(shiny.maxRequestSize=30*1024^2)
server <- function(input, output, session) {
company_data <- reactive({
req(input$file1,input$asset,input$energy_co)
data <- read_lines(input$file1$datapath)
text_df <- as_data_frame(data)
company_data <- text_df %>%
filter(str_detect(terms, input$asset)) %>%
filter(str_detect(terms, input$energy_co)) %>%
distinct(.)
company_data
})
output$table <- renderTable({
company_data()
})
output$downloadData <- downloadHandler(
filename = function() {
paste(company_data, ".csv", sep = "")
},
content = function(file) {
write.csv(company_data(), file1, row.names = FALSE)
}
)
}
shinyApp(ui, server)
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()
}
)
}
)
)
Is there a method to output (UI end) Shiny plots to PDF for the app user to download? I've tried various methods similar to those involving ggplot, but it seems downloadHandler can't operate in this way. For example the following just produces broken PDF's that don't open.
library(shiny)
runApp(list(
ui = fluidPage(downloadButton('foo')),
server = function(input, output) {
plotInput = reactive({
plot(1:10)
})
output$foo = downloadHandler(
filename = 'test.pdf',
content = function(file) {
plotInput()
dev.copy2pdf(file = file, width=12, height=8, out.type="pdf")
})
}
))
Very grateful for assistance.
Solved. The plot should be saved locally with pdf(), not the screen device (as with dev.copy2pdf). Here's a working example: shiny::runGist('d8d4a14542c0b9d32786'). For a nice basic model try:
server.R
library(shiny)
shinyServer(
function(input, output) {
plotInput <- reactive({
if(input$returnpdf){
pdf("plot.pdf", width=as.numeric(input$w), height=as.numeric(input$h))
plot(rnorm(sample(100:1000,1)))
dev.off()
}
plot(rnorm(sample(100:1000,1)))
})
output$myplot <- renderPlot({ plotInput() })
output$pdflink <- downloadHandler(
filename <- "myplot.pdf",
content <- function(file) {
file.copy("plot.pdf", file)
}
)
}
)
ui.R
require(shiny)
pageWithSidebar(
headerPanel("Output to PDF"),
sidebarPanel(
checkboxInput('returnpdf', 'output pdf?', FALSE),
conditionalPanel(
condition = "input.returnpdf == true",
strong("PDF size (inches):"),
sliderInput(inputId="w", label = "width:", min=3, max=20, value=8, width=100, ticks=F),
sliderInput(inputId="h", label = "height:", min=3, max=20, value=6, width=100, ticks=F),
br(),
downloadLink('pdflink')
)
),
mainPanel({ mainPanel(plotOutput("myplot")) })
)
(Hello), just use pdf :
library(shiny)
runApp(list(
ui = fluidPage(downloadButton('foo')),
server = function(input, output) {
plotInput = reactive({
plot(1:10)
})
output$foo = downloadHandler(
filename = 'test.pdf',
content = function(file) {
pdf(file = file, width=12, height=8)
plotInput()
dev.off()
})
}
))
EDIT : I don't know... It's weird. A workaround is to use dev.copy2pdf like you did in the first place but in the reactive function instead downloadHandler :
## server.R
library(shiny)
shinyServer(
function(input, output) {
plotInput <- reactive({plot(rnorm(1000))
dev.copy2pdf(file = "plot.pdf")
})
output$myplot <- renderPlot({ plotInput() })
output$foo <- downloadHandler(
filename <- "plot.pdf",
content <- function(file) {
file.copy("plot.pdf", file)
})
}
)