Using R and Plot.Ly - How to Script Saving My Output as a Webpage

Using R and plot.ly - how do I script saving my output as a webpage

Assign the plot_ly object to a variable and then use htmlwidgets::saveWidget() to save the actual file, like so:

library(plotly)
set.seed(100)
d <- diamonds[sample(nrow(diamonds), 1000), ]
p <- plot_ly(d, x = carat, y = price, text = paste("Clarity: ", clarity),
mode = "markers", color = carat, size = carat)
htmlwidgets::saveWidget(as_widget(p), "index.html")

Using R and plot.ly - how do I script saving my output as a webpage

Assign the plot_ly object to a variable and then use htmlwidgets::saveWidget() to save the actual file, like so:

library(plotly)
set.seed(100)
d <- diamonds[sample(nrow(diamonds), 1000), ]
p <- plot_ly(d, x = carat, y = price, text = paste("Clarity: ", clarity),
mode = "markers", color = carat, size = carat)
htmlwidgets::saveWidget(as_widget(p), "index.html")

save plotly plot to local file and insert into html

Option 1: Use plotly's offline functionality in your Jupyter Notebook (I suppose you are using a Jupyter Notebook from the link you are providing). You can simply save the whole notebook as a HTML file. When I do this, the only external reference is to JQuery; plotly.js will be inlined in the HTML source.

Option 2: The best way is probably to code directly against plotly's JavaScript library. Documentation for this can be found here: https://plot.ly/javascript/

Update: Calling an internal function has never been a good idea. I recommend to use the approach given by @Fermin Silva. In newer versions, there now is also a dedicated function for this: plotly.io.to_html (see https://plotly.com/python-api-reference/generated/plotly.io.to_html.html)

Hacky Option 3 (original version for reference only): If you really want to continue using Python, you can use some hack to extract the HTML it generates. You need some recent version of plotly (I tested it with plotly.__version__ == '1.9.6'). Now, you can use an internal function to get the generated HTML:

from plotly.offline.offline import _plot_html
data_or_figure = [{"x": [1, 2, 3], "y": [3, 1, 6]}]
plot_html, plotdivid, width, height = _plot_html(
data_or_figure, False, "", True, '100%', 525)
print(plot_html)

You can simply paste the output somewhere in the body of your HTML document. Just make sure that you include a reference to plotly in the head:

<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

Alternatively, you can also reference the exact plotly version you used to generate the HTML or inline the JavaScript source (which removes any external dependencies; be aware of the legal aspects however).

You end up with some HTML code like this:

<html>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
<!-- Output from the Python script above: -->
<div id="7979e646-13e6-4f44-8d32-d8effc3816df" style="height: 525; width: 100%;" class="plotly-graph-div"></div><script type="text/javascript">window.PLOTLYENV=window.PLOTLYENV || {};window.PLOTLYENV.BASE_URL="https://plot.ly";Plotly.newPlot("7979e646-13e6-4f44-8d32-d8effc3816df", [{"x": [1, 2, 3], "y": [3, 1, 6]}], {}, {"showLink": false, "linkText": ""})</script>
</body>
</html>

Note: The underscore at the beginning of the function's name suggests that _plot_html is not meant to be called from external code. So it is likely that this code will break with future versions of plotly.

How to setup plotly script in Rmarkdown to reduce HTML file

It would be helpful if I knew more about what you're doing. Are you going to use RMD for the plots in general, or is this just to create a local dependency? You could change your library for Plotly by adding it. Or are you planning on storing the JS file in your local files? If you added it to your library, you would only do that once; whenever you need to bundle, it's already there—no work required (until you update Plotly).

Without knowing exactly the steps you'll take down the road, I'll provide the essentials to accomplish this in a couple of different ways.

Regardless of where you place the file, as long as the file is there, you will only need to create the dependency list and add it to the plot.

First I've put it all together as if it's going into your library; after that, I break it down further, showing the differences between using the library and other locations in your directory.

Altogether:

library(plotly)

data(hobbs, package="plotly")

# plotly with partial bundle
plt <- plot_ly(type = "bar", data = hobbs, x = ~nms, y = ~r) %>% partial_bundle()
plt # take a look

# look at the dependencies
plt$dependencies # 5th one is plotly_basic

# take the temp location shown in dependencies and copy file to library
# library location dependencies must be within pkg sub dir htmlwidgets
getLib <- system.file(package = "plotly", "htmlwidgets/lib/plotlyjs")

# use the info in dependency and library to copy the file
file.copy(from = paste0(plt$dependencies[[5]]$src$file, # temp locale
plt$dependencies[[5]]$script),
to = paste0(getLib, plt$dependencies[[5]]$script)) # library

# inspect what you expect
list.files(getLib)

# change the dependency in the plot

# create dependency list for library
pbund <- htmltools::htmlDependency(
name = plt$dependencies[[5]]$name,
version = plt$dependencies[[5]]$version,
src = "htmlwidgets/lib/plotlyjs",
script = plt$dependencies[[5]]$script,
package = "plotly" )

# replace dependency in plot
plt$dependencies[[5]] <- pbund

# inspect what you expect
plt$dependencies[[5]]

plt

Broken down with direction:

To start: getting the file you need

You could definitely download the JS files, but there is an easier way. The easiest way to do this is to call partial_bundle and see what it's pointing to. However, you wouldn't do this in an RMD with your actual plots unless you changed the chunk options to eval=F, but then why include it? The collection of this js script may be better suited for the rarely ran (like when Plotly updates) R script (you would need it for other computers or if Plotly was updated).

I created a plot, called partial_bundle, and took a look at the dependencies.

library(plotly)

data(hobbs, package="plotly")
head(hobbs)

# partial plotly bundle
plt <- plot_ly(type = "bar", data = hobbs, x = ~nms, y = ~r) %>% partial_bundle()
plt # take a look; ugly, but it works

invisible(lapply(1:length(plt$dependencies),
function(k) message(plt$dependencies[[k]]$name)))
# typedarray
# jquery
# crosstalk
# plotly-htmlwidgets-css
# plotly-basic

plt$dependencies[[5]]
# List of 12
# $ name : chr "plotly-basic"
# $ version : chr "2.5.1"
# $ src :List of 2
# ..$ href: chr "https://cdn.plot.ly"
# ..$ file: chr "/var/folders/zp/rgt0rwln7xq132_rnrmhfb400000gn/T//RtmpFtB0bB"
# $ meta : NULL
# $ script : chr "plotly-basic-2.5.1.min.js"
# $ stylesheet : NULL
# $ head : NULL
# $ attachment : NULL
# $ all_files : logi FALSE
# $ local : logi TRUE
# $ minified : logi TRUE
# $ partial_bundle: chr "auto"
# - attr(*, "class")= chr "html_dependency"

If you look at the last call, plt$dependencies[[5]], you've got some useful information.

What this tells me is that there is a CDN (content data network on the web), but there is also a temp file (yours will look a little different).

# cdn
plt$dependencies[[5]]$src$href
# $href
# [1] "https://cdn.plot.ly"

# tempfile path
plt$dependencies[[5]]$src$file
# $file
# [1] "/var/folders/zp/rgt0rwln7xq132_rnrmhfb400000gn/T//RtmpFtB0bB"

list.files(plt$dependencies[[5]]$src$file)

You should see the file name "plotly-basic-2.5.1.min.js", when you list.files(). You've already downloaded the file to a temporary location just by calling the plot.

You could leave the file where it is for now (not great long term); You could put it somewhere else in your local directory, or you could add it to your plotly library package.

There is also a URL. You could download the file (if you can't get to your temp files or for any other reason you chose.

This is how you would assemble the entire URL:

link <- with(plt$dependencies[[5]], paste0(src$href, "/", script))

If you wanted to download this file to a directory you started in the object tf, you can download this in R using:

download.file(url = link, destfile = tf)

Moving the file

If you choose to copy the file to somewhere else in your directory or add it to your Plotly library, the move is essentially the same.

Since I don't know your directory or where you'd place it, I will demonstrate moving it to the Plotly library.

Library directory

To get the directory of any package in your library, use system.file(). Most packages that use htmlwidgets have a YAML that governs the dependencies for that package. Plotly doesn't (makes this even easier).

I chose to put the file with the other Plotly JS files in the subdirectory htmlwidgets/lib/plotlyjs. It must be within /plotly/htmlwidgets, but beyond that is up to you.

getLib <- system.file(package = "plotly", "htmlwidgets/lib/plotlyjs")
# [1] "/Library/Frameworks/R.framework/Versions/4.1/Resources/library/plotly/htmlwidgets/lib/plotlyjs"
Copying a file to a new directory

Whether you want to move it to your library or another location, this will work.

file.copy(from = paste0(plt$dependencies[[5]]$src$file,
plt$dependencies[[5]]$script),
to = paste0(getLib, plt$dependencies[[5]]$script))

# inspect what you expect
list.files(getLib)

Creating the dependency object

Once you've got the file in the spot you want it, as long as the file is there, you only need to assemble the dependency list and add it to your plot. So if your RMD has the plots you're using it with, the only part that requires coding is creating the dependency list and adding it to the plot. If you launch the RMD from more than one computer, keep the code to access, copy, or move the JS file in a chunk set to eval=F or commented out unless needed.

If you were to use the library versus not using the library, there is one crucial difference for the dependency list—all_files. If it is not in your library, this must be set to FALSE. If it is in your library, it won't matter for this project (true or false).

Here's the dependency I had shown earlier with an arrow pointing out all_files.

plt$dependencies[[5]]
# List of 12
# $ name : chr "plotly-basic"
# $ version : chr "2.5.1"
# $ src :List of 2
# ..$ href: chr "https://cdn.plot.ly"
# ..$ file: chr "/var/folders/zp/rgt0rwln7xq132_rnrmhfb400000gn/T//RtmpFtB0bB"
# $ meta : NULL
# $ script : chr "plotly-basic-2.5.1.min.js"
# $ stylesheet : NULL
# $ head : NULL
# $ attachment : NULL
# $ all_files : logi FALSE <- all_files is here!
# $ local : logi TRUE
# $ minified : logi TRUE
# $ partial_bundle: chr "auto"
# - attr(*, "class")= chr "html_dependency"

You won't want to overwrite this dependency, you want to replace it. (It will cause you problems if you try to piecemeal this.)

Using the package htmltools, this is how you can create it. Your src is going to be the absolute path, with two exceptions.

Exception 1: It's stored in the same folder as the RMD, if it's an RMD.
Exception 2: It's stored in your plotly library; use path within the package, if you put it in your library.

Library

Here's a dependency for my library.

pbund <- htmltools::htmlDependency(
name = plt$dependencies[[5]]$name,
version = plt$dependencies[[5]]$version,
src = "htmlwidgets/lib/plotlyjs",
script = plt$dependencies[[5]]$script,
package = "plotly" )

Which is exactly the same as:

pbund <- htmltools::htmlDependency(
name = "plotly-basic",
version = "2.5.1",
src = "htmlwidgets/lib/plotlyjs",
script = "plotly-basic-2.5.1.min.js",
package = "plotly")
Another directory (not library)

Here's the same dependency, but pointing to the temp file.

pbund <- htmltools::htmlDependency(
name = plt$dependencies[[5]]$name,
version = plt$dependencies[[5]]$version,
src = plt$dependencies[[5]]$src$file,
script = plt$dependencies[[5]]$script,
all_files = F)

Which is exactly the same as:

pbund <- htmltools::htmlDependency(
name = "plotly-basic",
version = "2.5.1",
src = "/var/folders/zp/rgt0rwln7xq132_rnrmhfb400000gn/T//RtmpFtB0bB",
script = "plotly-basic-2.5.1.min.js",
all_files = F)

Then replace the dependency.

Now add it to your plot

plt$dependencies[[5]] <- pbund
# inspect what you expect
plt$dependencies[[5]]

How to put many plotly plots in a single file and add text

You can use iframe to include HTML files generated by plotly. Find a minimal example below.

R code to generate index.html (source):

library(plotly)
set.seed(100)
d <- diamonds[sample(nrow(diamonds), 1000), ]
p <- d %>% plot_ly(x = ~carat, y = ~price, text = ~paste("Clarity: ", clarity),
+ mode = "markers", color = ~carat, size = ~carat)
htmlwidgets::saveWidget(as_widget(p), "index.html")

HTML to include index.html using the iframe tag:

<!DOCTYPE html>
<html>
<body>
<h1>My Heading</h1>
<p>My paragraph.</p>
<iframe src="index.html" width = '500px' height = '300px'></iframe>
</body>
</html>

Add custom js file to R html widget output?

You can add javascript through htmlwidget function onStaticRenderComplete()

//////////////////////////////////////////////////
javascript <- HTML(paste("

//here write your own javscript

", sep=''))

//pass this javascript to prepend function and assign
it to your graph object.

p <- prependContent(p,onStaticRenderComplete(javascript))

htmlwidgets::saveWidget(p, plotlyoutput, selfcontained =
FALSE)

Another method for external js file is ::

follow this link

Embedding an R htmlwidget into existing webpage

R: saving multiple html widgets together

If format doesn't matter too much, you can merge the widgets using tagList and save them directly:

htmltools::save_html(tagList(widget_1, widget_2, widget_3, widget_4), file = "C://Users//Me//Desktop//widgets.html")

(It goes without saying that you will need to edit the filepath!)

If you want to control the layout of the widgets, you can wrap each in a div, and then style those:

doc <- htmltools::tagList(
div(widget_1, style = "float:left;width:50%;"),
div(widget_2,style = "float:left;width:50%;"),
div(widget_3, style = "float:left;width:50%;"),
div(widget_4, style = "float:left;width:50%;")
)

htmltools::save_html(html = doc, file = "C://Users//Me//Desktop//widgets.html")


Related Topics



Leave a reply



Submit