2

I am using the R programming language. I am interested in learning how to save several "html widgets" together. I have been able to manually create different types of html widgets:

#widget 1
library(htmlwidgets)
library(leaflet)
library(RColorBrewer)

# create map data
map_data <- data.frame(
  "Lati" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Longi" = c(-79.3871, -79.3860, -79.3807, -79.3806, -79.3957),
  "Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
  "First_Name" = c("John", "James", "Jack", "Jason", "Jim"),
  "Last_Name" = c("Smith", "Charles", "Henry", "David", "Robert"),
  "vehicle" = c("car", "van", "car", "none", "car")
)

kingdom <- c("Economist", "Lawyer", "Teacher")
my_palette <- brewer.pal(3, "Paired")
factpal <- colorFactor(my_palette, levels = kingdom)

groups <- unique(map_data$Job)

# finalize map
map <- leaflet(map_data) %>%
  addTiles(group = "OpenStreetMap") %>% 
  addCircleMarkers(~Longi, ~Lati, popup = ~Job,
                   radius = 10, weight = 2, opacity = 1, color = ~factpal(Job),
                   fill = TRUE, fillOpacity = 1, group = ~Job
  )

widget_1 = map %>%
  addLayersControl(overlayGroups = groups, options = layersControlOptions(collapsed = FALSE)) %>%
  addTiles() %>%
  addMarkers(lng = ~Longi, 
             lat = ~Lati, 
             popup = ~paste("Job", Job, "<br>", 
                            "First_Name:", First_Name, "<br>", 
                            "Last_Name:", Last_Name, "<br>", "vehicle:", vehicle, "<br>"))

widget 2:

##### widget 2

library(plotly)
library(ggplot2)

p_plot <- data.frame(frequency = c(rnorm(31, 1), rnorm(31)),
                     is_consumed = factor(round(runif(62))))
p2 <- p_plot %>%
  ggplot(aes(frequency, fill = is_consumed)) +
  geom_density(alpha = 0.5)     

widget_2 = ggplotly(p2)

widget 3:

#####widget_3

today <- Sys.Date()
tm <- seq(0, 600, by = 10)
x <- today - tm
y <- rnorm(length(x))
widget_3 <- plot_ly(x = ~x, y = ~y, mode = 'lines', text = paste(tm, "days from today"))

widget 4:

####widget_4

library(igraph)
library(dplyr)
library(visNetwork)


Data_I_Have <- data.frame(
   
    "Node_A" = c("John", "John", "John", "Peter", "Peter", "Peter", "Tim", "Kevin", "Adam", "Adam", "Xavier"),
    "Node_B" = c("Claude", "Peter", "Tim", "Tim", "Claude", "Henry", "Kevin", "Claude", "Tim", "Henry", "Claude")
)


graph_file <- data.frame(Data_I_Have$Node_A, Data_I_Have$Node_B)


colnames(graph_file) <- c("Data_I_Have$Node_A", "Data_I_Have$Node_B")

graph <- graph.data.frame(graph_file, directed=F)
graph <- simplify(graph)


nodes <- data.frame(id = V(graph)$name, title = V(graph)$name)
nodes <- nodes[order(nodes$id, decreasing = F),]
edges <- get.data.frame(graph, what="edges")[1:2]

widget_4 = visNetwork(nodes, edges) %>%   visIgraphLayout(layout = "layout_with_fr") %>%
    visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

From here, I found another stackoverflow post where a similar question was asked: Using R and plot.ly, how to save multiples htmlwidgets to my html?

In this post, it explains how to save several html widgets together - the person who answered the question wrote a function to do so:

library(htmltools)
save_tags <- function (tags, file, selfcontained = F, libdir = "./lib") 
{
  if (is.null(libdir)) {
    libdir <- paste(tools::file_path_sans_ext(basename(file)), 
                    "_files", sep = "")
  }
  htmltools::save_html(tags, file = file, libdir = libdir)
  if (selfcontained) {
    if (!htmlwidgets:::pandoc_available()) {
      stop("Saving a widget with selfcontained = TRUE requires pandoc. For details see:\n", 
           "https://github.com/rstudio/rmarkdown/blob/master/PANDOC.md")
    }
    htmlwidgets:::pandoc_self_contained_html(file, file)
    unlink(libdir, recursive = TRUE)
  }
  return(htmltools::tags$iframe(src= file, height = "400px", width = "100%", style="border:0;"))
}

I tried using this function to save the 4 widgets together:

save_tags(widget_1, widget_2, widget_3, widget_4)

But doing so, I got the following error:

 Error in dirname(file) : a character vector argument expected 

Is there a straightforward and simple way for saving multiple html widgets together?

Thanks

NOTE: I know that you can use the combineWidgets() function in R:

library(manipulateWidget)
combineWidgets(widget_1, widget_2, widget_3, widget_4)

enter image description here

However, I am working with a computer that has no internet access or USB ports. This computer has a pre-installed copy of R with limited libraries (it has all the libraries used throughout my question except "manipulateWidget"). I am looking for the simplest way to save multiple html widgets together (e.g. is this possible in base R)?

Thanks

ismirsehregal
  • 30,045
  • 5
  • 31
  • 78
stats_noob
  • 5,401
  • 4
  • 27
  • 83
  • Update: From the following link https://stackoverflow.com/questions/40540802/using-r-and-plot-ly-how-to-save-multiples-htmlwidgets-to-my-html, I tried : htmltools::save_html(c(widget_1, widget_2, widget_3, widget_4), "y.html") .... but i got the following error: Error in as.character(x) : cannot coerce type 'closure' to vector of type 'character' – stats_noob Jan 07 '21 at 04:44
  • You should simplify your question to include a *minimal* reproducible example. It's way to much work to run your full set of code, so you are limiting yourself to people who can spot the error at a glance. – user2554330 Jan 07 '21 at 10:31

1 Answers1

4

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")
O.A
  • 141
  • 1
  • 5
  • thank you for your reply! is the tagList() command only possible with the "shiny library"? is it possible to run this without an internet connection? – stats_noob Jan 07 '21 at 15:19
  • regarding the second code you kindly provided (creating the "doc" object). Suppose there were 5 widgets (for argument sake, let's say widget_5 = widget_1). Is it still possible to use the "float" option and place 5 widgets on the same page without scaling the "width" options? thank you for all your help! – stats_noob Jan 07 '21 at 15:23
  • for example: 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_5, style = "float:left;width:50%;"), div(widget_4, style = "float:left;width:50%;") ) – stats_noob Jan 07 '21 at 15:25
  • 1
    It looks like `tagList` is part of htmltools to me, try `htmltools::tagList`? – O.A Jan 07 '21 at 15:29
  • 2
    I'm not quite sure I understand your second question, sorry. What format are you hoping to achieve? The float and width options are independent. Width can be set as either a percentage or an absolute size (replace `%` with `px`). `float:left` just means that the figures wrap onto the same line if there is space. You can add as many widgets as you like. – O.A Jan 07 '21 at 15:36
  • 2
    I would recommend staying with the width as a percentage. It makes the layout much easier to manage. Especially if you have different size screens the output will be shown on. If you go the pixel route, you may end up with widgets stacking on each other. – nate Jan 07 '21 at 18:41
  • thank you everyone for your replies! is there a way to specify the order that the widgets appear in the final file? For example, suppose you have 6 widgets : is there a way to use the tagList() command so that they end up in this specific order https://imgur.com/a/BHNgK8F ? thanks! – stats_noob Jan 09 '21 at 22:34
  • @O.A : this is what I was reffering to. If possible, can you please take a look at my question? https://stackoverflow.com/questions/65802298/r-adjusting-titles-in-html-files thanks – stats_noob Jan 20 '21 at 02:35