I'm getting a namespace error when I run the code below as follows: Warning: Error in : 'zipr' is not an exported object from 'namespace:zip'
[No stack trace available]. Any suggestions on what this could be due to? Thanks in advance.
library(shiny)
library(ggplot2)
ui <- fluidPage(
plotOutput("p1"),
plotOutput("p2"),
plotOutput("p3"),
downloadButton("allgraphs", "Download")
)
server = function(input, output) {
df<-data.frame(q=c(1,3,5,7,9),w=c(2,4,6,8,10),z=c(1,2,3,4,5))
p1 <- reactive({
ggplot(df,aes(x=q,y=w)) + geom_point()
})
p2 <- reactive({
ggplot(df,aes(x=z,y=w))+geom_point()
})
p3 <- reactive({
ggplot(df,aes(x=q,y=z))+geom_point()
})
output$p1 <- renderPlot({
p1()
})
output$p2 <- renderPlot({
p2()
})
output$p3 <- renderPlot({
p3()
})
output$allgraphs = downloadHandler(
filename = function() {
'all_images.zip'
},
content = function(fname) {
fs <- replicate(3, tempfile(fileext = ".png"))
ggsave(fs[1], p1())
ggsave(fs[2], p2())
ggsave(fs[3], p3())
zip::zipr(zipfile=fname, files=fs)
},
contentType = "application/zip")
}
shinyApp(ui, server)
You need to update your zip package to latest version. I had the same issue with version 1.0.0 of zip which doesn't exports any zipR object and openxlsx loading would fail. The upgrade of zip to v2.1.0, which indeed exports a zipR object, solved the issue.
Related
My app allows the user to generate some plots and save them as png.
I want the app as well to update a csv file based on some inputs made into the app by the user.
For example purposes, I created a toy app that generates a csv file in a given folder.
In both cases, the app doesn't display any error message or info, but it doesn't store any file anywhere.
library(shiny)
library(ggplot2)
library(AlphaPart)
ui <- fluidPage(
selectInput("var1","Select var1", choices = names(iris)),
selectInput("var2","Select var2", choices = names(iris)),
plotOutput("myplot"),
downloadLink("downloadPlot", label = icon("download")))
server <- function(input, output, session) {
data <- reactive(iris)
var1 <- reactive({input$var1})
var2 <- reactive({input$var2})
# Genearte plot
draw_boxplot <- function(data, var1, var2){
ggplot(data=data(), aes(x=.data[[input$var1]], y = .data[[input$var2]]))+
geom_boxplot()
}
plot1 <- reactive({
req(data(), input$var1, input$var2)
draw_boxplot(data(), var1(), var2())
})
output$myplot <- renderPlot({
plot1()
})
#Download
output$downloadPlot <- downloadHandler(
filename = function() {
return("Plot.png")
},
content = function(file) {
png(file)
print(plot1())
dev.off()
})
#Write csv
eventReactive(input$downloadPlot, {
dat <- as.data.frame(c(input$num_var_1, input$num_var_2))
write.csv(dat, "C:/dat.csv", row.names = FALSE)
})
}
shinyApp(ui, server)
library(shiny)
library(ggplot2)
library(AlphaPart)
library(spsComps)
ui <- fluidPage(
selectInput("var1","Select var1", choices = names(iris)),
selectInput("var2","Select var2", choices = names(iris)),
plotOutput("myplot"),
downloadLink("downloadPlot", label = icon("download")))
server <- function(input, output, session) {
data <- reactive(iris)
var1 <- reactive({input$var1})
var2 <- reactive({input$var2})
# Genearte plot
draw_boxplot <- function(data, var1, var2){
ggplot(data=data(), aes(x=.data[[input$var1]], y = .data[[input$var2]]))+
geom_boxplot()
}
plot1 <- reactive({
req(data(), input$var1, input$var2)
draw_boxplot(data(), var1(), var2())
})
output$myplot <- renderPlot({
plot1()
})
#Download
downloaded <- reactiveVal(0)
output$downloadPlot <- downloadHandler(
filename = function() {
return("Plot.png")
},
content = function(file) {
png(file)
print(plot1())
dev.off()
on.exit({spsComps::incRv(downloaded)})
})
#Write csv
observeEvent(downloaded(), {
dat <- as.data.frame(c(input$num_var_1, input$num_var_2))
utils::write.csv(dat, "dat.csv", row.names = FALSE)
print("File saved")
}, ignoreInit = TRUE)
}
shinyApp(ui, server)
Unfortunately, you can't observe download event. So here we do, introduce another reactiveVal which we can change inside the download event so we will know if the download button has been clicked.
spsComps::incRv is a short hand function for downloaded(isolate(downloaded()) + 1), so it increase the reactiveVal every time by one.
use on.exit on the end to make sure this happens only when the plot is successful.
Instead of using eventReactive, observeEvent should be used since you are not returning any value but just write a file.
I want to create several wordclouds, using wordcloud and wordcloud2 packages.
I can create a download for the wordcloud created by the wordcloud package, but as soon as I render a wordcloud2-wordcloud, the download button breaks (only allows to download .html instead of .png).
I've added an example to reproduce it:
library("shiny")
library("wordcloud")
library("wordcloud2")
library("tm")
ui <- fluidPage(plotOutput("plot1"), downloadButton('plot1download'))
server <- function(input, output, session) {
output$plot1 <- renderPlot({
wordcloud(data(crude))
})
output$plot2 <- renderWordcloud2({
wordcloud2(demoFreq)
})
output$plot1download <- downloadHandler(
filename = function() {
paste('wordcloud', '.png', sep='')
},
content = function(file) {
device <- function(..., width, height) grDevices::png(...)
ggsave(file, plot = wordcloud(data(crude)), device = device)
}
)
}
shinyApp(ui, server)
The code above works, but if I add another plot (plotOutput("plot2")), it breaks:
library("shiny")
library("wordcloud")
library("wordcloud2")
library("tm")
ui <- fluidPage(plotOutput("plot1"), downloadButton('plot1download'), wordcloud2Output("plot2"))
server <- function(input, output, session) {
output$plot1 <- renderPlot({
wordcloud(data(crude))
})
output$plot2 <- renderWordcloud2({
wordcloud2(demoFreq)
})
output$plot1download <- downloadHandler(
filename = function() {
paste('wordcloud', '.png', sep='')
},
content = function(file) {
device <- function(..., width, height) grDevices::png(...)
ggsave(file, plot = wordcloud(data(crude)), device = device)
}
)
}
shinyApp(ui, server)
Anyone has an idea why this happens and how to resolve the issue?
This seems to be a bug in the CRAN version of wordcloud2. Install the development version from GitHub with
remotes::install_github("lchiffon/wordcloud2")
for a fix.
I am trying to download output from wordcloud2 on shiny.
My code is as below:
library(shiny)
library(htmlwidgets)
library(webshot)
ui <- shinyUI(fluidPage(mainPanel(
wordcloud2Output("wordcl"),
downloadButton(outputId = "savecloud"),
downloadButton(outputId = "savecloud2")
)))
server <- shinyServer(function(input, output, session) {
wordcl <- reactive ({
wordcloud2(demoFreq, color = "random-light", backgroundColor = "grey")
})
output$wordcl <- renderWordcloud2({ wordcl() })
##### SOLUTION 1 #########
output$savecloud <- downloadHandler(
filename = "word.png",
content = function(cloud) {
file.copy(wordcl(), cloud)
})
##### SOLUTION 2 ##########
output$savecloud2 <- downloadHandler(
saveWidget(wordcl(), file="temp.html", selfcontained = F),
webshot("temp.html", file = "word2.png",
cliprect = "viewport")
)
})
shinyApp(ui = ui, server = server)
I have tried two styles using downloadhandler as shown in the code but they return empty results.
Any insight on why they downloadhandler doesn't work or redirection on how best to effect the download function will be appreciated.
I managed to make my download work by using an example of download handler function posted on LeafletMaps here: Why is webshot not working with leaflets in R shiny?
My updated code is as below:
library(shiny)
library(htmlwidgets)
library(webshot)
library(wordcloud2)
#webshot::install_phantomjs()
ui <- shinyUI(fluidPage(mainPanel(
wordcloud2Output("wordcl"),
downloadButton(outputId = "savecloud")
)))
server <- shinyServer(function(input, output, session) {
wordcl <- reactive ({
wordcloud2(demoFreq, color = "random-light", backgroundColor = "grey")
})
output$wordcl <- renderWordcloud2({
wordcl()
})
output$savecloud <- downloadHandler(
filename = paste("wordcloud", '.png', sep=''),
content = function(file) {
owd <- setwd(tempdir())
on.exit(setwd(owd))
saveWidget(wordcl(), "temp.html", selfcontained = FALSE)
webshot("temp.html", delay =15, file = file, cliprect = "viewport")
})
})
shinyApp(ui = ui, server = server)
The solution given on the link seems to combine the solutions I was trying to implement in my original post.
The only issue is that it does not work when the app is deployed on shiny.io
Is it possible to download a ggplotly() object as .png like a ggplot() object in a shiny application which you open in a browser. I have found some ways to download a ggplot but none for ggplotly. If there is no way is there some hacky alternative?
library(shiny)
library(plotly)
ui <- fluidPage(
plotlyOutput("plot"),
verbatimTextOutput("event"),
downloadButton("download","Download Plot")
)
server <- function(input, output) {
# renderPlotly() also understands ggplot2 objects!
save<-reactive({
plot_ly(mtcars, x = ~mpg, y = ~wt)
})
output$plot <- renderPlotly({
ggplotly(save())
})
output$download <- downloadHandler(
filename = function() {
paste("down", ".png", sep="")
},
content = function(file) {
ggsave(file, plot = save())
}
)
}
shinyApp(ui, server)
I'm simply looking to return a user-produced plot (built in ggplot) or a data table from an app built from modules and a plotting helper function. I've seen many posts about downloadHandler being very finicky and there even appears to be open issues with some of downloadHandler's behaviours. The odd behaviour I'm getting, which I haven't seen posts about, is that it returns an html page of my app instead of the plot, regardless of how I try to save the plot (i.e., using pdf/png devices, ggsave(), etc.), or whether I use suspendWhenHidden. I can run the plot saving code external to Shiny and it works fine. I'm running all of this from the browser (Firefox, though Chrome does the same) on a mac, with recently updated everything.
Example code below.
Modules:
library(shiny)
library(ggplot2)
# UI module
modUI <- function(id, label="inputvalues") {
ns <- NS(id)
tagList(
numericInput(ns("mean"), "Mean",value = NULL),
numericInput(ns("sd"),"Std. Dev.",value = NULL),
actionButton(ns("draw"),"Draw plot"),
downloadButton(ns("dlPlot"), "Download Plot")
)
}
# Server Logic module
mod <- function(input, output, session) {
x <- reactiveValues(data=NULL)
observeEvent(input$draw, {
x$data <- rnorm(100,input$mean,input$sd)
})
return(list(dat = reactive({x$data}),
m = reactive({input$mean}),
s = reactive({input$sd})
)
)
}
Plotting helper function:
showPlot <- function(data, m, s) {
d <- data.frame(data)
p <- ggplot(d, aes(x=d, y=d)) +
geom_point() +
geom_vline(xintercept=m)
p
}
UI and Server calls:
ui <- navbarPage("Fancy Title",id = "tabs",
tabPanel("Panel1",value = 1,
sidebarPanel(
modUI("input1")
),
mainPanel(plotOutput("plot1"))
)
)
server <- function(input, output, session) {
y <- callModule(mod, "input1")
output$plot1 <- renderPlot({
if (is.null(y$dat())) return()
showPlot(data.frame(y$dat()), y$m(), y$s())
})
output$dlPlot <- downloadHandler(
filename="~Plot_Download.pdf",
content=function(file){
pdf(filename, file)
p
dev.off()
}
)
}
shinyApp(ui, server)
Thanks as always for any help!
Finally figured out an answer to this, based in large part on this post. The answer is to create a server module specifically for the download (which can take the session and namespace info), and then to call that module in the server. Additional and updated code below:
The new download module:
dlmodule <- function(input, output, session) {
output$dlPlot <- downloadHandler(
filename="Plot_Download.pdf",
content=function(file){
ggsave(file, device = pdf, width = 7,height = 5,units = "in",dpi = 200)
}
)
}
The updated server call:
server <- function(input, output, session) {
y <- callModule(mod, "input1")
output$plot1 <- renderPlot({
if (is.null(y$dat())) return()
showPlot(data.frame(y$dat()), y$m(), y$s())
})
dl.y <- callModule(dlmodule, "input1")
}
Everything else stays the same.