Как сохранить график ggplot как фрагмент кода html
Я создаю HTML-документ, создавая различные объекты с ggplotly()
и htmltools функции, такие как h3()
а также html()
, Затем я отправляю их в виде списка htmltools::save_html()
создать HTML-файл.
Я хотел бы добавить диаграммы ggplot непосредственно в виде изображений, а не прикреплять все сюжетные колокольчики и свистки. В конце я создам автономный html-файл (без зависимостей), и сюжетная линия сделает этот файл слишком большим.
Есть ли какая-то функция, которая преобразует объект ggplot в некоторый объект типа html? Или мне нужно сохранить ggplot как файл.png, а затем прочитать файл.png в какой-то объект, который я добавляю в список в функции save_html()?
Мой код R выглядит примерно так:
library("tidyverse")
library("plotly")
library("htmltools")
HTMLOut <- "c:/Users/MrMagoo/My.html")
df <- data.frame(x=1:25, y=c(1:25*1:25))
g7 <- ggplot(df,aes(x=x, y=y)) + geom_point()
p7 <- ggplotly(g7) # I would like to use something other than ggplotly here. Just capturing the ggplot as an image would be fine.
# create other objects to add to the html file
t7 <- h2(id="graph7", "Title for graph #7")
d7 <- p("description of graph 7")
save_html(list(t7, p7, d7), HTMLOut)
# of course, the real code has many more objects in that list – more graphs, text, tables, etc.
Я хотел бы заменить объект plotly (p7) чем-то, что просто представляет g7 таким образом, чтобы не вызвать ошибку в функции save_html.
Я надеялся найти функцию, которая могла бы напрямую кодировать BaseG64 объект ggplot, но мне кажется, что сначала мне нужно вывести объект 'ggplot' в виде файла.png (или SVG, согласно Teng L ниже), затем base64-encode Это. Я надеялся, что есть более прямой путь, но я могу в конечном итоге сделать это, как в /questions/34364437/konvertirovat-r-izobrazheniya-v-base-64/34364440#34364440, заканчивая его
g7img <- "<img src=\"data:image/png;base64,(base64encode string)\""
g7img <- htmltools::html(g7img)
4 ответа
Я закончил тем, что сгенерировал временный файл изображения, а затем закодировал его в base64 в функции, которую я назвал encodeGraphic()
(заимствование кода из поста LukeA):
library(ggplot2)
library(RCurl)
library(htmltools)
encodeGraphic <- function(g) {
png(tf1 <- tempfile(fileext = ".png")) # Get an unused filename in the session's temporary directory, and open that file for .png structured output.
print(g) # Output a graphic to the file
dev.off() # Close the file.
txt <- RCurl::base64Encode(readBin(tf1, "raw", file.info(tf1)[1, "size"]), "txt") # Convert the graphic image to a base 64 encoded string.
myImage <- htmltools::HTML(sprintf('<img src="data:image/png;base64,%s">', txt)) # Save the image as a markdown-friendly html object.
return(myImage)
}
HTMLOut <- "~/TEST.html" # Say where to save the html file.
g <- ggplot(mtcars, aes(x=gear,y=mpg,group=factor(am),color=factor(am))) + geom_line() # Create some ggplot graph object
hg <- encodeGraphic(g) # run the function that base64 encodes the graph
forHTML <- list(h1("My header"), p("Lead-in text about the graph"), hg)
save_html(forHTML, HTMLOut) # output it to the html file.
Если вы хотите сохранить сюжет как динамический plotly
график, вы могли бы использовать htmlwidgets::saveWidget
, Это создаст отдельный HTML-файл.
Вот минимальный пример:
library(tidyverse);
library(plotly);
library(htmlwidgets);
df <- data.frame(x = 1:25, y = c(1:25 * 1:25))
gg <- ggplot(df,aes(x = x, y = y)) + geom_point()
# Save ggplotly as widget in file test.html
saveWidget(ggplotly(gg), file = "test.html");
Я думаю, что вы хотите, может быть близко к одному из следующих:
Кажется, вы создаете отчет в формате HTML, но еще не зарегистрировали RMarkdown. Поставляется с кодировкой Base64. Когда вы создаете отчет RMarkdown,
pandoc
автоматически преобразует любые графики в элемент HTML внутри документа, поэтому отчет является автономным.SVG участки. Скорее всего, это не то, что вам нужно, но графики SVG основаны на языке разметки и могут быть легко переносимы. Уточнить
.svg
расширение при использованииggsave()
и вы должны получить изображение SVG. Обратите внимание, что SVG является реализацией графика как есть, поэтому, если он может быть огромным по размеру файла, если у вас есть тысячи форм и линий.
Это расширение поста Maurits Evers . В этом ответе я показываю , как организовать несколько сюжетных графиков в одном и том же html- файле:
library("plotly")
library("htmltools")
# a small helper function to avoid repetition
my_func <- function(..., title){
## Description:
## A function to add title to put multiple gg plotly objects under a html heading
##
## Arguments:
## ...: a list of gg objects
## title: a character vector to specify the heading text
# get the ... in list format
lst <- list(...)
# create the heading
tmp_title <- htmltools::h1(title)
# convert each ggplot to ggplotly and put them under the same div html tag
tmp_plot <- lapply(lst, ggplotly) |>
htmltools::div()
# return the final object as list
return(list(tmp_title, tmp_plot))
}
# a toy data
df <- data.frame(x = 1:25, y = c(1:25 * 1:25))
# the ggplot object using the toy data
gg <- ggplot(df,aes(x = x, y = y)) + geom_point()
# put everything in order
final_list <- list(my_func(obj = list(gg, gg, gg), title = "The first heading"),
my_func(obj = list(gg, gg), title = "The second heading"))
# write to disk as a unified HTML file
htmltools::save_html(html = final_list,
file = "index.html"))
Отказ от ответственности: я специально сделал это, чтобы избежать использования пакета R widgetframe и полностью соответствовать документации plotly-r. Вы можете прочитать ссылку, если вам удобно добавлять дополнительную зависимость и дополнительный уровень абстракции. Я предпочитаю использовать пакеты тогда и только тогда, когда это необходимо. :)