Adjust edge label position in mediation diagram with DiagrammeR? - r

I am trying to draw a standard triangular mediation diagram using DiagrammeR in R (it can also interpret graphviz code). On the whole, it's working fine but the edge label text gets placed oddly. The bottom edge label is not centered and the two angled edge labels are positioned at different heights (see the red lines in the diagram below). Is there a way to manually assign positions to edge text or get something more consistent?`
library(DiagrammeR)
# Create a node data frame (ndf)
ndf <- create_node_df(
n = 3,
label = c("Experimental\nTreatment", "Some\nMediator", "Outcome\nof Interest"),
shape = rep("rectangle", 3),
style = "empty",
fontsize = 6,
fixedsize = TRUE,
height = .5,
width = .75,
color = "gray40",
x = c(1, 2, 3),
y = c(1, 2, 1)
)
# Create an edge data frame (edf)
edf <- create_edge_df(
from = c(1, 1, 2),
to = c(2, 3, 3),
label = c("1.1*", "2.0*", "-0.33***"),
fontsize = 6,
minlen = 1,
color = "gray40",
)
# Create a graph with the ndf and edf
graph <- create_graph(
nodes_df = ndf,
edges_df = edf
)
graph %>%
render_graph()

I would also love to know the answer to this.
I have tried to delete the default "layout" graph attribute and set direction of graph layout via:
graphAttr <- DiagrammeR::get_global_graph_attrs(graph)
But, I get the following error:
Error: 'get_global_graph_attrs' is not an exported object from 'namespace:DiagrammeR'
....which it is, consequently, I am stuck.

After fiddling with DiagrammeR for a while, I ended up switching to the LaTeX diagramming package TikZ. It allows for enormous control of every aspect of the diagram but can be overwhelming. TikZ would require a bit of tweaking, also, to get diagrams into HTML output if that's important. For a presentation using LaTeX's Beamer class for slides, generating TikZ code with a function in R worked well. That TikZ code was then written to a text file that could be imported automatically via the LaTeX command \input{path/to/file.txt} or just copied and pasted into my slides.
See the code for two DiagrammeR solutions and the TikZ solution, here: https://stackoverflow.com/a/64886536/893399

Related

R: Plot too large to fit into window

I made a phylogenetic tree plot with the igraph package.
The problem is, that my tree is too big to fit into the saved image.
I'm using Rstudio and usually saving my plots manually.
With smaller trees, I was able to enlarge the plot window of Rstudio to make the plot fit into the image, without the nodes overlapping each other.
Unfortunately, this isn't working with my latest plot.
I tried to save it with png(), pdf() and jpeg() with different width and height, but it still doesn't fit properly.
Either the nodes overlap each other or only a part of the plot is visible in the image.
The only solution I found so far was to decrease the label size. But in the end, you can't read anything.
Thank you in advance for your help.
Here is my code:
id <- c("Spirochaetota","Brachyspirae","Brevinematia","Leptospirae","Spirochaetia","sk6","Brachyspirales","Brachyspiraceae","Brachyspira",
"Brevinematales","bo1","Brevinemataceae","Brevinema","bf2","Leptospirales","Leptonemataceae","Leptonema","lg2","Leptospiraceae","Leptospira",
"LeptospiraA","LeptospiraB","lg3","lf1","Turneriellales","Turneriellaceae","Turneriella","tf1","Borreliales","Borreliaceae","Borrelia",
"Borreliella","Sphaerochaetales","Sphaerrochaetaceae","Sphaerochaeta","SphaerochaetaA","sg15","SpirochaetalesA","SpirochaetaceaeA",
"SpirochaetaA","sf1","SpirochaetalesC","Alkalispirochaetaceae","Alkalispirochaeta","Salinispiraceae","Salinispira","SpirochaetaD","sg1",
"sf6","SpirochaetalesD","sdf1","SpirochaetalesE","SpirochaetaceaeB","Oceanispirochaeta","SpirochaetaE","SpirochaetaF","SpirochaetaG","sg2",
"Treponematales","Treponemataceae","Treponema","TreponemaB","TreponemaC","TreponemaD","TreponemaF","tg7","TreponemataceaeB","TreponemaE",
"TreponemaG","TreponemaH","tg5","tf3","so11")
links <- data.frame(from = c("Spirochaetota","Spirochaetota","Spirochaetota","Spirochaetota","Spirochaetota","Brachyspirae",
"Brachyspirales","Brachyspiraceae","Brevinematia","Brevinematia","Brevinematales","Brevinemataceae",
"Brevinematales","Leptospirae","Leptospirales","Leptonemataceae","Leptonemataceae","Leptospirales",
"Leptospiraceae","Leptospiraceae","Leptospiraceae","Leptospiraceae","Leptospirales","Leptospirae",
"Turneriellales","Turneriellaceae","Turneriellales","Spirochaetia","Borreliales","Borreliaceae",
"Borreliaceae","Spirochaetia","Sphaerochaetales","Sphaerrochaetaceae","Sphaerrochaetaceae","Sphaerrochaetaceae",
"Spirochaetia","SpirochaetalesA","SpirochaetaceaeA","SpirochaetalesA","Spirochaetia","SpirochaetalesC",
"Alkalispirochaetaceae","SpirochaetalesC","Salinispiraceae","Salinispiraceae","Salinispiraceae","SpirochaetalesC",
"Spirochaetia","SpirochaetalesD","Spirochaetia","SpirochaetalesE","SpirochaetaceaeB","SpirochaetaceaeB",
"SpirochaetaceaeB","SpirochaetaceaeB","SpirochaetaceaeB","Spirochaetia","Treponematales","Treponemataceae",
"Treponemataceae","Treponemataceae","Treponemataceae","Treponemataceae","Treponemataceae","Treponematales",
"TreponemataceaeB","TreponemataceaeB","TreponemataceaeB","TreponemataceaeB","Treponematales","Spirochaetia"),
to = c("Brachyspirae","Brevinematia","Leptospirae","Spirochaetia","sk6","Brachyspirales",
"Brachyspiraceae","Brachyspira","Brevinematales","bo1","Brevinemataceae","Brevinema",
"bf2","Leptospirales","Leptonemataceae","Leptonema","lg2","Leptospiraceae",
"Leptospira","LeptospiraA","LeptospiraB","lg3","lf1","Turneriellales",
"Turneriellaceae","Turneriella","tf1","Borreliales","Borreliaceae","Borrelia",
"Borreliella","Sphaerochaetales","Sphaerrochaetaceae","Sphaerochaeta","SphaerochaetaA","sg15",
"SpirochaetalesA","SpirochaetaceaeA","SpirochaetaA","sf1","SpirochaetalesC","Alkalispirochaetaceae",
"Alkalispirochaeta","Salinispiraceae","Salinispira","SpirochaetaD","sg1","sf6",
"SpirochaetalesD","sdf1","SpirochaetalesE","SpirochaetaceaeB","Oceanispirochaeta","SpirochaetaE",
"SpirochaetaF","SpirochaetaG","sg2","Treponematales","Treponemataceae","Treponema",
"TreponemaB","TreponemaC","TreponemaD","TreponemaF","tg7","TreponemataceaeB",
"TreponemaE","TreponemaG","TreponemaH","tg5","tf3","so11"))
net <- graph_from_data_frame(d = links, vertices = id, directed = T)
lay = layout.reingold.tilford(net)
plot(net, vertex.shape = "none",
vertex.label.font = 3,
vertex.label.cex = 0.3,
edge.arrow.size = 0.3,
rescale = F,
ylim = c(0.7,3.4),xlim = c(-8,23.2), asp = 0,
layout = lay)
If everything works, it should look similar to this smaller tree. this one does not include the nodes of the code above:
This is my result of the big tree so far. It contains the nodes in the code above:
The only solution I came up with so far is to somehow fit the plot into the plot panel and save it as a SVG file. Afterwards, I edited it using inkscape:
You can plot the tree graph as a dendrogram.
Drawing it left to right allows to put all of the taxon labels in a readable column:
library(igraph)
net <- graph_from_data_frame(d = links, vertices = id, directed = F)
lay <- layout.reingold.tilford(net)
plot_dendrogram(cluster_fast_greedy(net))
There is also:
links %>%
graph_from_data_frame() %>%
as_adjacency_matrix() %>%
dist() %>%
hclust() %>%
as.dendrogram() %>%
plot()

DiagrammeR: Adjust font size within node

I want to create a flowchart with the DiagrammeR Package in R. Within some nodes, I want to reduce the font size of some parts of the text.
Consider the following example in R:
library("DiagrammeR")
# Create a node data frame (ndf)
ndf <- create_node_df(n = 4,label = c("aaa", "bbb",
"Same size\nThese letters\nshould be smaller",
"ccc"))
# Create an edge data frame (edf)
edf <- create_edge_df(from = c(1, 2, 3, 3),
to = c(4, 3, 1, 4))
# Create a graph with the ndf and edf
graph <- create_graph(nodes_df = ndf,
edges_df = edf)
# Print graph
graph %>%
render_graph()
The font size of the node in the middle should partly be reduced. The text "Same size" should be kept as it is. The font size of the text "These letters should be smaller" should be reduced.
Question: How could I adjust the font size for some parts of the text within a node?
Try
fixedsize = FALSE.
This adjusts the node to stretch to fit the words. It's documented here under Create_nodes but they really do not explain it very well.
The behavior to me was Fixedsize=True (in that no matter what we put in it.. the size was fixed).
So I've tried fixedsize = FALSE and it worked!
Were you able to make it work?
It looks like you can add style="filled"; reference: https://www.rdocumentation.org/packages/DiagrammeR/versions/1.0.0/topics/create_node_df
ndf <- create_node_df(n = 4, style="filled", label = c("aaa", "bbb",
"Same size\nThese letters\nshould be smaller",
"ccc"))

How to specify order of glyph layers in rbokeh?

I am trying to build a network visualisation using the rbokeh package.
library(igraph)
library(rbokeh)
library(dplyr)
g <- random.graph.game(n=100,p=0.3)
L <- as.data.frame(igraph::layout_with_fr(g)) %>% rename(x=V1,y=V2)
url1 <- 'http://icons.veryicon.com/png/Business/Flat%20Finance/person.png'
p <- figure(xlab = "x", ylab = "y", height = 500,width=1000,xgrid=F,ygrid=F,webgl = T,
xaxes = F,yaxes = F,h_symmetry = T,v_symmetry = T) %>%
ly_lines(x = L$x,y=L$y,color = '#FFA700', width = 4, alpha = 0.2) %>%
ly_image_url(x = L$x, y=L$y, image_url = url1, w = rep(0.1,vcount(g)), h=rep(0.2,vcount(g)),
anchor = "center",lname = 'nodes')
The resulting visualisation looks as intended except for the fact that the lines are drawn on top of the image glyphs. Is there a way to control the visual order of the layers in a way that the nodes (images) are drawn on top with lines drawn behind?
The issue here is using webgl = TRUE. For more details, see the Bokeh documentation (see both the "support" and "notes" sections. The main points there are that not all glyphs can be rendered with WebGL (yes for lines, no for images) and that "Glyphs drawn using WebGL are drawn on top of glyphs that are not drawn in WebGL."
If you get rid of webgl = TRUE, you should be in good shape!
Also, to further answer the overall question of how to control the order of layers, the answer is that outside of edge cases like this where one layer was rendered with WebGL and the other wasn't, layers are drawn in the order that they are specified.

Define margins of PDF used for boxplot rendering

When I render a boxplot on a PDF device in R there is a large white space besides the graph, especially at the top that i intent to reduce.
My script is basically just:
data <- read.csv("input.csv")
pdf(file="output.pdf", width=4, height=5)
boxplot(data, xlab="input graphs", ylab="vertex count")
This leads to something like:
where the grey outline indicates the end of the document.
I tried to use the par attributes "mar" and "mai" as described in https://stat.ethz.ch/R-manual/R-devel/library/graphics/html/par.html but it had no effect.
boxplot(data, mar=c(0,0,0,0=, mai=c(0,0,0,0))
Do you have an advice how I can gain whitespace control? I want to have zero outer whitespace as the generated graph will be used in a Latex environment that provides sufficient spacings on its own. I am using Ubuntu as OS.
Define mar right after pdf. Try this as an example
pdf(file = "test.pdf", width = 5, height = 5)
par(mar = c(5, 5, 0.05, 0.05))
set.seed(42)
plot(rnorm(20))
dev.off()

Plotting directed multigraphs in R

I've never used any graph plotting package in R, I'm familiar with basic plotting commands and with ggplot2 package. What I've found (but not tried out yet) are Rgraphviz, network and igraph packages. So I'd like to ask you, which package has simplest learning curve and satisfies following requirements:
Has simple layout engines (spring layout, random, ...)
Tries to draw multiple edges between two vertices so that they would not overlap. As a bonus it would be nice to being able to adjust this.
Can draw loops.
Vertex and edge labels, vertex and edge size and color are adjustable.
(No need for any of the graph algorithms like link analysis, shortest path, max flow etc, but nice, if present)
The igraph package seems to fulfill your requirements, with the tkplot() function helping adjusting the final layout if needed.
Here is an example of use:
s <- cbind(A=sample(letters[1:4], 100, replace=TRUE),
B=sample(letters[1:2], 100, replace=TRUE))
s.tab <- table(s[,1], s[,2])
library(igraph)
s.g <- graph.incidence(s.tab, weighted=T)
plot(s.g, layout=layout.circle,
vertex.label=c(letters[1:4],letters[2:1]),
vertex.color=c(rep("red",4),rep("blue",2)),
edge.width=c(s.tab)/3, vertex.size=20,
vertex.label.cex=3, vertex.label.color="white")
With the interactive display (there's a possibility of using rgl for 3D display), it looks like (I have slightly moved one vertex afterwards):
tkplot(s.g, layout=layout.circle, vertex.color=c(rep("red",4),rep("blue",2)))
Finally, you can even export you graph into most common format, like dot for graphviz.
The multigraph R package can be useful as well. For the above example bmgraph plots such graph:
library("multigraph")
bmgraph(s.tab, layout = "circ", pch = 16:16, pos = 0, vcol = 6:7, lwd = 3, cex = 9)
And for a directed version:
bmgraph(s.tab, "circ", pch = 16:16, pos = 0, vcol = 6:7, lwd = 3, cex = 9, directed = TRUE)

Resources