Follow up from :
https://groups.google.com/forum/#!topic/shiny-discuss/u7gwXc8_vyY
I have the exact same R Shiny structured program as the user in the post, except I am using the googleVis Shiny package for my plots. For example, here is a plot of a gVis table:
output$gvisTable <- renderGvis( {
if (is.null(dataset))
return(NULL)
gvisTable(dataset)
})
EDIT:
My code to save ggplots:
server.R
name <- paste0(input$filename, ".png")
print(p)
if(input$savePlot) {
ggsave(name, p, type="cairo-png")
}
ui.R (in sidePanel)
wellPanel(
textInput('filename', "Filename"),
checkboxInput('savePlot', "Check to save")
)
This is what I am using to try to save gVis plots:
name <- paste0(input$filename, ".png")
if(input$savePlot) {
png(name, *INPUT GVIS PLOT HERE*, type="cairo-png")
dev.off()
}
This does not work: I get the error: 'non-numeric argument to binary operator'
I can't find a way to allow the user to download a gVis plot. I can't use the method in the linked post because you cannot 'print' a gVis plot.
Also, the files are locally saved to my R working directory, but I plan to upload this app to the web. Where would the files be saved for the user? Ideas?
I see no png method documented for gvis objects.
There are two ways to "print" documented in the help page linked from the googleVis main Index page for print.gvis. The default method (when the tag is NULL or "html") is to send a Java script page to your browser. The other (when you set tag="chart" is to construct an html file with the name you give it. I suppose you could arrange something with system commands sent to a running instance of a particular browser, but for that you should use different SO tags so that you attract the interest of people using the same software as you. (I'm using a Mac with Firefox and having no difficulties seeing the "printed" output.) If you plan to "upload it to the web", then you need to have a server. Is my impression this is a bit new for you correct?
print(GTM, tag="chart", file="test.html")
#created in my working directory
Related
I have the dynamic plot that I want. I have a problem knowing how to export the plot to an HTML file so I can share the plot with others. I tried what I have below but it doesn't save the file.
# save the widget
library(htmlwidgets)
setwd("C:/Users/12083/Desktop/")
saveWidget(p, file=paste0( getwd(), "C:/Users/12083/Desktop/ggplotlyAreachart.html"))
use auto_open=False:
plotly.offline.plot(fig, filename = 'filename.html', auto_open=False);
As of version 4.0, the write_html() function is available on go.Figure objects as well, so you can do fig.write_html("path/to/file.html") directly now too.
you can see the documentation here: https://plotly.com/python/interactive-html-export/
I've created a scatter plot with ggplot2 and would like to link the data points with corresponding sound files. In a shiny app it should then be possible to click on or hover over a data point to play the sound file. While I manage to get the plot into a shiny app, I am struggling with the inclusion of tags$audio, as described here, into the plot.
library(shiny)
library(plotly)
ui <- fluidPage(
plotlyOutput('scatter')
)
server <- function(input, output) {
output$scatter <- renderPlotly({
ggplotly(p)
})
}
shinyApp(ui = ui, server = server)
The plotly plot displays a tooltip with the info per data point, among others also the URL for the sound file. See the working example here: https://chart-studio.plotly.com/~petergi/1.
The ggplot2 code contains the URL information in the aes 'text'.
p <- ggplot(without_outliers) +
aes(x = T2, y = T1, label = labels, col = next_label,
text = paste0("URL: ", "https://www.yyyy.zz/audio/", tolower(bundle), ".mp3"))
Any hint to how to bring an audio player to the scatter plot's data points in shiny would be highly appreciated.
In the meantime, I found a working solution in using the R package ggiraph, which enhances ggplot2 with tooltip and onclick functionalities, when used in a shiny application. In a nutshell, a geom_point_interative call can have an onClick argument, which in turn then is a call to a Javascript function to play the audio (without opening a new window or a player).
library(ggplot2)
library(ggiraph)
library(shiny)
p <- ggplot(mtcars, aes(wt, mpg))+
geom_point_interactive(onclick="var audio= new Audio(\"https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3\"); audio.play();")
x <- girafe(ggobj = p)
To allow for all different data points in a data frame to be associated with their corresponding audio files, the data frame should be modified to contain a new column with the individual javascript code to play the audio.
An example shiny app can be found here.
Thank you Peter, I managed to get this working with help from your pointers. I know this is a late response but I hope it helps if someone else runs into a similar issue. First, I recommend reviewing the examples shared above.
I managed to get something like this working. However, instead of defining the audio and playing it with the onclick argument, I created a separate javascript file and sourced it through the shiny applet.
I created a separate file called fileNames.js where I defined each variable. Using the example above with only one audio file, this would be: var audio= new Audio("https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3");.
In the R shiny applet, I changed the onclick argument in geom_point_interactive() to the javascript code to play the audio file. In your example, the string would be simply audio.play();. For whatever reason passing the multi-line javascript code to the onclick argument didn't work for me.
Early in the ui call, I included includeScript(path = "fileNames.js") to source the javascript into the shiny app.
Here's another helpful example in case someone stumbles upon this thread as I did: https://www.ardata.fr/en/post/2019/05/24/whats-up-ggiraph/
I've made different plots (more than a hundred) for a project and I haven't capture them on the way (yes it's bad , i know). Now, I need to save them all at once but without running again my script (which takes hours). Is there a way to do so within Rstudio ?
Edit: All the plot are already there and I don't want to run them again.
In RStudio, every session has a temporary directory that can be obtained using tempdir(). Inside that temporary directory, there is another directory that always starts with "rs-graphics" and contains all the plots saved as ".png" files. Therefore, to get the list of ".png" files you can do the following:
plots.dir.path <- list.files(tempdir(), pattern="rs-graphics", full.names = TRUE);
plots.png.paths <- list.files(plots.dir.path, pattern=".png", full.names = TRUE)
Now, you can copy these files to your desired directory, as follows:
file.copy(from=plots.png.paths, to="path_to_your_dir")
Additional feature:
As you will notice, the .png file names are automatically generated (e.g., 0078cb77-02f2-4a16-bf02-0c5c6d8cc8d8.png). So if you want to number the .png files according to their plotting order in RStudio, you may do so as follows:
plots.png.detials <- file.info(plots.png.paths)
plots.png.detials <- plots.png.detials[order(plots.png.detials$mtime),]
sorted.png.names <- gsub(plots.dir.path, "path_to_your_dir", row.names(plots.png.detials), fixed=TRUE)
numbered.png.names <- paste0("path_to_your_dir/", 1:length(sorted.png.names), ".png")
# Rename all the .png files as: 1.png, 2.png, 3.png, and so on.
file.rename(from=sorted.png.names, to=numbered.png.names)
Hope it helps.
Although this discussion has been inactive for a while, there are some persons, like myself, who still come across the same problem, and the other solutions don't really seem to even get what the actual question is.
So, hands on. Your plot history gets saved in a variable called .SavedPlots. You can either access it directly, assign it to another variable in code or do the latter from the plots window.
# ph for plot history
ph <- .SavedPlots
In R 3.4.2, I could index ph to reproduce the corresponding plot in a device. What follows is rather straightforward:
Open a new device (png, jpeg, pdf...).
Reproduce your plot ph[index_of_plot_in_history].
Close the device (or keep plotting if it is a pdf with multiple pages).
Example:
for(i in 1:lastplot) {
png('plotname.png')
print(ph[i])
dev.off()
}
Note: Sometimes this doesn't happen because of poor programming. For instance, I was using the MICE package to impute many datasets with a large number of variables, and plotting as shown in section 4.3 of this paper. Problem was, that only three variables per plot were displayed, and if I used a png device in my code, only the last plot of each dataset would be saved. However, if the plots were printed to a window, all the plots of each dataset would be recorded.
If your plots are 3d, you can take a snapshot of all your plots and save them as a .png file format.
snapshot3d(filename = '../Plots/SnapshotPlots.png', fmt = 'png')
Or else, the best way is to create a multi-paneled plotting window using the par(mfrow) function. Try the following
plotsPath = "../Plots/allPlots.pdf"
pdf(file=plotsPath)
for (x in seq(1,100))
{
par(mfrow = c(2,1))
p1=rnorm(x)
p2=rnorm(x)
plot(p1,p2)
}
dev.off()
You can also use png, bmp, tiff, and jpeg functions instead of pdf. You can read their advantages and disadvantages and choose the one you think is good for your needs.
I am not sure how Rstudio opens the device where the plot are drawn, but I guess it uses dev.new(). In that case one quick way to save all opened graphs is to loop through all the devices and write them using dev.print.
Something like :
lapply(dev.list(),function(d){dev.set(d);dev.print(pdf,file=file.path(folder,paste0("graph_",d,".pdf"))})
where folder is the path of the folder where you want to store your graph (could be for example folder="~" if you are in linux and want to store all your graph in your home folder).
If you enter the following function all that will follow will be save in a document:
pdf("nameofthedocument.pdf")
plot(x~y)
plot(...
dev.off()
You can also use tiff(), jpg()... see ?pdf
I created a shiny app and now i want to plot a chart to pdf. So, is there any way to print a googlevis Chart to pdf in R.
I know its not possible directly, as stated in the help pages. But is there a way to print a static image (similar to a screenshot)? If possible without sweave/knitr?
Thank you in advance
You can do this using wkhtmltopdf, which you need to install and possibly add to your system path. I have got this working for other googlevis objects, where in some cases I did not need the --enable-javascript --javascript-delay option....
output$downloadmap <- downloadHandler("mymap.pdf" ,
content = function(file) {
#print gmap googlevis R object to a html file
print(gmap, file="gmap.html")
#call to wkhtmltopdf installed on server/pc to convert html file to pdf.
#add a delay otherwise (i got an) empty plot
system("wkhtmltopdf --enable-javascript --javascript-delay 2000 gmap.html gmap.pdf")
#copy pdf file to output
file.copy("gmap.pdf", file)
#remove created files from local storage
file.remove("gmap.pdf")
file.remove("gmap.html")
}
)
I do a lot of data exploration in R and I would like to keep every plot I generate (from the interactive R console). I am thinking of a directory where everything I plot is automatically saved as a time-stamped PDF. I also do not want this to interfere with the normal display of plots.
Is there something that I can add to my ~/.Rprofile that will do this?
The general idea is to write a script generating the plot in order to regenerate it. The ESS documentation (in a README) says it well under 'Philosophies for using ESS':
The source code is real. The objects are realizations of the
source code. Source for EVERY user modified object is placed in a
particular directory or directories, for later editing and
retrieval.
With any editor allows stepwise (or regionwise) execution of commands you can keep track of your work this way.
The best approach is to use a script file (or sweave or knitr file) so that you can just recreate all the graphs when you need them (into a pdf file or other).
But here is the start of an approach that does the basics of what you asked:
savegraphs <- local({i <- 1;
function(){
if(dev.cur()>1){
filename <- sprintf('graphs/SavedPlot%03d.pdf', i)
dev.copy2pdf( file=filename )
i <<- i + 1
}
}
})
setHook('before.plot.new', savegraphs )
setHook('before.grid.newpage', savegraphs )
Now just before you create a new graph the current one will be saved into the graphs folder of the current working folder (make sure that it exists). This means that if you add to a plot (lines, points, abline, etc.) then the annotations will be included. However you will need to run plot.new in order for the last plot to be saved (and if you close the current graphics device without running another plot.new then that last plot will not be saved).
This version will overwrite plots saved from a previous R session in the same working directory. It will also fail if you use something other than base or grid graphics (and maybe even with some complicated plots then). I would not be surprised if there are some extra plots on occasion that show up (when internally a plot is created to get some parameters, then immediatly replaced with the one of interest). There are probably other things that I have overlooked as well, but this might get you started.
you could write your own wrapper functions for your commonly used plot functions. This wrapper function would call both the on-screen display and a timestamped pdf version. You could source() this function in your ~/.Rprofile so that it's available every time you run R.
For latice's xyplot, using the windows device for the on-screen display:
library(lattice)
my.xyplot <- function(...){
dir.create(file.path("~","RPlots"))
my.chart <- xyplot(...)
trellis.device(device="windows",height = 8, width = 8)
print(my.chart)
trellis.device(device = "pdf",
file = file.path("~", "RPlots",
paste("xyplot",format(Sys.time(),"_%Y%m%d_%H-%M-%S"),
".pdf", sep = "")),
paper = "letter", width = 8, height = 8)
print(my.chart)
dev.off()
}
my.data <- data.frame(x=-100:100)
my.data$y <- my.data$x^2
my.xyplot(y~x,data=my.data)
As others have said, you should probably get in the habit of working from an R script, rather than working exclusively from the interactive terminal. If you save your scripts, everything is reproducible and modifiable in the future. Nonetheless, a "log of plots" is an interesting idea.