I would like users to be able to upload a file, see the graphs displayed and then offer them a download link where they can download all graphs as pdfs in a zip or tar file. I have managed to do all steps except for the last. It works for one graph but not for many.
Here is my code
shinyServer(function(input, output) {
#takes the uploaded file and transforms it into the way I want it
dataInput<-reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
data<-read.csv(inFile$datapath, fileEncoding="UTF-16", sep="\t")
data$date<-ymd(data$StartDate)
data$date2<-format(data$date,"%b %y")
})
#plot 1
plotInput1<-function(){
data <- dataInput()
dataByCountry<-aggregate(Queries~date+Category, sum,data=data)
ggplot(dataByCountry, aes(x=date, y=Queries, group=Category, color=Category))+geom_line(size=1.5)+
}
#plot 2
plotInput2<-function(){
data <- dataInput()
categoryQueries<-aggregate(Queries~date+Geo+Category, sum,data=data)
ggplot(categoryQueriesLastyear, aes(x=Category, y=Queries, fill="#3369e8"))+geom_bar(stat='identity', fill="#3369e8")+
}
#render plots
output$haha1 <- renderPlot({plotInput1()})
output$haha2 <- renderPlot({plotInput2()})
#I can download one plot but how do I donwload all of them?
output$foo <- downloadHandler(
filename ="graphs.pdf",
content = function(file) {
pdf(file, width=12, height=6.3)
print(plotInput1()
dev.off()
})
})
})
Any help would be highly appreciated
Related
I have a shiny app to generate a .txt file to download.
In addition, I would like to keep a copy of the file that users generate in my shiny server.
the server function looks like :
server <- function(input, output, session){
data_gen <- reactive({
d1= data.frame(...)
d2= data.frame(...)
result <- list(d1=d1, d2=d2)
return(result)
})
create_file <- reactive({
sink("/srv/shiny-server/S3/file.txt",append = TRUE)
print(data_gen()$d1)
print(data_gen()$d2)
sink()
})
output$downloadData <- downloadHandler(
filename = function() {"input.txt"},
content = function(file) {
sink(file,append = TRUE)
print(data_gen()$d1)
print(data_gen()$d2)
sink()
}
)
}
I'm able to download the data but the app does not react to the create_file function and it does not write a copy into shiny server.
Any Idea how could I fix this ?
Your create_file function is a reactive. Reactive functions only evaluate when 1) their output is required, and 2) their inputs have changed. Neither appears to apply here.
What you could do is move the contents of create_file inside your downloadhandler. content must receive a function that returns a file, but the function can do other things first. So try the following:
server <- function(input, output, session){
data_gen <- reactive({
d1= data.frame(...)
d2= data.frame(...)
result <- list(d1=d1, d2=d2)
return(result)
})
output$downloadData <- downloadHandler(
filename = function() {"input.txt"},
content = function(file) {
# save non-user copy
sink("/srv/shiny-server/S3/file.txt",append = TRUE)
print(data_gen()$d1)
print(data_gen()$d2)
sink()
# copy to be returned for user
sink(file,append = TRUE)
print(data_gen()$d1)
print(data_gen()$d2)
sink()
})
}
I have an R shiny which generates a dashboard with some plots.
I implemented a download button to download the report as a PDF using knitr. Here is part the problematic part of the code:
hist_pl <- reactive({
inFile <- input$file
if (is.null(inFile))
return(NULL)
dataf <- getDF()
h <- hist(dataf)
par(new = T)
plot(x = h$mids, y=ec(h$mids)*max(h$counts), col = rgb(0,0,0,alpha=0), axes=F,xlab=NA, ylab=NA)
})
output$hist1 <- renderPlot({
hist_pl()
})
The problem is as follow:
When I comment the 'renderPlot' part of the code, the histogram appears normally in the PDF report (but not in the dashboard). When I uncomment it, the histogram disappear from the PDF (and appear in the dashboard).
The code for the download button is fairly simple:
output$report = downloadHandler(
filename = 'myreport.pdf',
content = function(file) {
out = knit2pdf('input.Rnw', clean = TRUE)
file.rename(out, file) # move pdf to file for downloading
},
contentType = 'application/pdf'
)
and the input.Rnw file:
\documentclass{article}
\begin{document}
<<names>>=
input$Val1
input$Val2
#
<<>>=
#output$mpgPlot ## N.B. This threw an error! Cannot call an object like this from shiny
print(hist_pl())
#
<<>>=
print(hist_pl())
#
\end{document}
Can someone tell me what could the problem be?
I want to import a .RData file with fileInput but It doesn't work, I have this error message :
Error in my.data$TYPE_DE_TERMINAL : $ operator is invalid for
atomic vectors
dt <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
load(inFile$datapath)
})
GetData <- reactive({
my.data <- dt()
When I try my application with a .RData imported manually it works well (I remplaced dt() directly with a dataframe in my directory) ...
The following example solves the problem. It allows you to upload all .RData files.
Thanks to #Spacedman for pointing me to a better approach of loading the data:
Load the file into a new environment and get it from there.
For the matter of the example being "standalone" I inserted the top section that stores two vectors to your disk in order to load and plot them later.
library(shiny)
# Define two datasets and store them to disk
x <- rnorm(100)
save(x, file = "x.RData")
rm(x)
y <- rnorm(100, mean = 2)
save(y, file = "y.RData")
rm(y)
# Define UI
ui <- shinyUI(fluidPage(
titlePanel(".RData File Upload Test"),
mainPanel(
fileInput("file", label = ""),
actionButton(inputId="plot","Plot"),
plotOutput("hist"))
)
)
# Define server logic
server <- shinyServer(function(input, output) {
observeEvent(input$plot,{
if ( is.null(input$file)) return(NULL)
inFile <- isolate({input$file })
file <- inFile$datapath
# load the file into new environment and get it from there
e = new.env()
name <- load(file, envir = e)
data <- e[[name]]
# Plot the data
output$hist <- renderPlot({
hist(data)
})
})
})
# Run the application
shinyApp(ui = ui, server = server)
In my below example of a simple shiny app i recently created, im currently trying to include also the possibility of downloading a data frame that is created from the results. I mention here part of the server.R script in order to not make a huge post:
shinyServer(function(input, output) {
table_options<- list(lengthMenu = list(c(5,10,15,20),
c('5','10', '15', '20')), pageLength = 15, ordering=TRUE,
class = 'cell-border stripe',dom ='t',scrollX = TRUE,
fixedColumns = list(leftColumns = 2, rightColumns = 1))
inTable <- reactive({# upload a tsv file
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.table(inFile$datapath,header=input$header,
sep="\t",stringsAsFactors = FALSE)
}) #END REACTIVE
rv <- reactiveValues()
rv$data <- NULL # to further use it into the observeEvent below
observeEvent(input$goButton, {
df <- inTable()
# some data manipulation with df...
if(input$repo_option=="mimic"){
# some functions here that result to a data frame named final dat
rv$data <- final.dat
rv$data
}
else if(input$repo_option=="reverse"){
# similar procedure...
rv$data <- final.dat
rv$data
}
})
output$contents <- DT::renderDataTable({
expr=DT::datatable(rv$data, options=table_options,
extensions ='FixedColumns',selection="none")
})
output$downloadData <- downloadHandler(
filename = function() { paste("input$file1", ".csv", sep=",") },
content = function(file) {
write.csv(rv$data,file)
}
)
})
My main issue is that, although the output$contents works fine in the app, when i press the download button from the ui.R server (not posted here for simplicity), the download "pop-up" window appears, but the saving does not work. Thus, i suspect that is something wrong with the code in the downloadHandler function, but any ideas or help ?
I'm currently working on image processing application using R Shiny It uploads an image using file upload and then I need to read the image to do the image processing operations. server.R file is as follows.
library(shiny)
library(EBImage)
library(imager)
library(jpeg)
function(input, output) {
observe({
file_path <- input$files
if (is.null(file_path))
return(NULL)
file_path$datapath <- gsub("\\\\", "/", file_path$datapath)
img <- readImage(file_path$datapath)
equalized <- equalize(img,range = c(0, 1), levels = 256)
output$text <- renderText({
file_path$datapath
})
output$img <- renderImage({
list(src = file_path$datapath,
contentType = "image/jpg",
width = "50%",
height = "auto",
alt = "This is alternate text")
})
})
}
But this gives me the following error.
Warning: Error in readImage: Please supply at least one filename.
Stack trace (innermost first):
57: readImage
56: observerFunc
I managed to plot an equalized image using raster method. Here are some tips/tricks:
You put everything inside an observer which is a pretty bad idea, so I got rid of that.
Use req() when checking whether a file is uploaded, UI is rendered, etc instead of an if statement. `
if (is.null(file_path)) return(NULL)
There is no need to assign input$files to a variable, you can call input$files$datapath. Also gsub() is not needed in this case.
file_path <- input$files
file_path$datapath <- gsub("\\\\", "/", file_path$datapath)
equalized is calculated, but you don't use it anywhere.
Solution
Checking with req() whether a file is uploaded.
Get the extension of the file (splitting by ., getting the last element)
Plot the equalized image using the display() function with method = "raster".
Print datapath which points to a temp dir/file
See:
library(shiny)
library(EBImage)
library(imager)
library(jpeg)
ui <- fluidPage(
fileInput("files", "Upload a file"),
plotOutput("img"),
textOutput("txt")
)
server <- function(input, output) {
output$img <- renderPlot({
req(input$files)
st <- strsplit(input$files$name, split = "[.]")[[1]]
extension <- st[length(st)]
display(equalize(readImage(input$files$datapath, type = extension), range = c(0, 1), levels = 256), method = "raster")
})
output$txt <- renderText({
input$files$datapath
})
}
shinyApp(ui, server)
Using EBImage we can load an image into Rshiny and use it for further processing. Below code allows the user to upload an image and then same is displayed on shiny screen back.
library(shiny)
library(EBImage)
upload_image <- list()
ui <- fluidPage(
fileInput("file1", "Upload an Image"),
plotOutput("img")
)
server <- function(input, output) {
output$img <- renderPlot({
req(input$file1)
upload_image[[1]] <- readImage(input$file1$datapath)
plot(upload_image[[1]])
})
}
shinyApp(ui , server)