R Markdown: visNetWork not displayed in html output when using for loops (or functions)

1.7k Views Asked by At

My visNetwork is not displayed at all when the displaying is attempted in a for loop. In a regular R script, I use the print function and it works just fine, but it does not work in an R Markdown document.

Here is a (hopefully) reproducible example:

---
title: "I want my beautiful networks back!"
---

# First example that works

```{r}
require(visNetwork, quietly = TRUE)
# minimal example
nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(1,3))
vn <- visNetwork(nodes, edges, width = "100%")
vn # Or print(vn)
```

# When does it not work?

## In a for loop

```{r}
for (i in 1) vn
```

## In a for loop + using print

This will display the network in the Viewer.

```{r}
for (i in 1) print(vn)
```

## And also in functions

Same remark...

```{r}
foo <- function(x) print(x)
foo(vn)
```

I'm using Rstudio version Version 1.1.383 and here is the result of a sessionInfo()

R version 3.4.2 (2017-09-28)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.6

other attached packages:
[1] visNetwork_2.0.2
4

There are 4 best solutions below

3
On BEST ANSWER

I just found a little workaround, consisting the following steps:

  • Save plot as HTML
  • Include the HTML code in RMD file

Here an example:

```{r}
for (i in 1:3){
  visSave(vn, file = paste0("test",i,".html"))
}
```

```{r, results='asis'}
for (i in 1:3){
  cat(htmltools::includeHTML(paste0("test",i,".html")))
}
```
0
On

You can remove the !DOCTYPE by operating on the string.

cat (as.character(htmltools::includeHTML(paste0("vn",".html"))) %>%
  {gsub("<!DOCTYPE html>","",.,fixed = TRUE)} %>%
  {sub("\n","",.)}
)
0
On

Another solution is to use print(htmltools::tagList())

This prevents the !DOCTOOLS showing in the output.

```{r}
for (i in 1) print(htmltools::tagList(vn))
```

I came across the same issue / solution when working with Datatables and the solution was provided here by @Yihui: https://github.com/rstudio/DT/issues/67

Edit I've since realised that you need at least one visnetwork plotted outside of the loop, i.e. outside of print(htmltools::taglist()), otherwise the script to render is not added to the html file.

0
On

I had the same problem but also wanted to knit my Rmd from the command line, not within RStudio, to easily generate reports for many different parameters, e.g.:

Rscript -e "rmarkdown::render('graphical-res-vis-reports.Rmd', \
      params = list(tissue = '${tissue}'), \
      output_file = sprintf('graphical-analysis-results_%s.html','${tissue}'))"

The htmltools::includeHTML(html_path) trick worked well when knitting from within RStudio, but it spat out a pandoc error when I tried to knit it from the command line because it's effectively concatenating multiple standalone HTMLs, which does not result in a valid HTML format. (EDIT: the pandoc error may have also been because R from the command line was using a much older version of pandoc than RStudio, but using iframes is still much cleaner.)

I finally found a solution using iframes that works well. Here is a minimal reproducible example:

---
title: "Finally, a way to print visNetworks in a loop!"
---

```{r make networks}
require(visNetwork, quietly = TRUE)
# minimal example
nodes <- data.frame(id = 1:3)
edges <- data.frame(from = c(1,2), to = c(1,3))

html_list <- c()
for (i in 1:3){
    vn <- visNetwork(nodes, edges)
    outfile <- sprintf("vn_%s.html", i)
    visSave(vn, file=outfile)
    html_list <- c(html_list, outfile)
}
```

```{r plot networks, results="asis"}
for (i in html_list){
    print(htmltools::tags$iframe(title = "My embedded document", 
          src = f, height = "650", width = "900", frameBorder = "0"))
}
```

EDIT: Note that changing the iframe height and width doesn't resize the object from the HTML file. However, you can increase the size of the visNetwork HTML object with a simple text replacement. In this example, I remove the whitespace padding and change the size from 960x500 to 960x960:

visSave(v1, file = out_html)

# adjust browser window size 
cmd = sprintf('sed -i \'s|"browser":{"width":960,"height":500,"padding":40,"fill":false}|"browser":{"width":960,"height":960,"padding":0,"fill":false}|\' %s', out_html)
system(cmd)