R: Plot too large to fit into window - r

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()

Related

Highlight a Specific Section of a Treemap using Treemap package in R

I am using the Treemap package in R to highlight the number of COVID outbreaks in different settings. I am making a number of different reports using R Markdown. Each one describes a different type of settings and I would like to highlight that setting in the treemap for each report, showing what proportion of total outbreaks occur in the setting in question. For example you I am currently working on the K-12 school report and would like to highlight the box representing that category in the figure.
I was previously using an exploded donut pie chart however there were two many subcategories and the graph became hard to read.
I am picturing a way to change the label or border on one specific box, ie. put a yellow border around the box or make the label yellow. I found a way to do both these things for all the boxes but not just one specific box. I made this image using the snipping tool to further illustrate what the desired outcome might look like. The code to generate the treemap can be found in the link below. It looks like this:
# library
library(treemap)
# Build Dataset
group <- c(rep("group-1",4),rep("group-2",2),rep("group-3",3))
subgroup <- paste("subgroup" , c(1,2,3,4,1,2,1,2,3), sep="-")
value <- c(13,5,22,12,11,7,3,1,23)
data <- data.frame(group,subgroup,value)
# treemap
treemap(data,
index=c("group","subgroup"),
vSize="value",
type="index"
)
This is the most straightforward information I can find about the package, this is where I took the sample image and code from: https://www.r-graph-gallery.com/236-custom-your-treemap.html
It looks like the treemap package doesn't have a built-in way to do this. But we can hack it by using the data frame returned by treemap() and adding a rectangle to the appropriate viewport.
# Plot the treemap and save the data used for plotting.
t = treemap(data,
index = c("group", "subgroup"),
vSize = "value",
type = "index"
)
# Add a rectangle around subgroup-2.
library(grid)
library(dplyr)
with(
# t$tm is a data frame with one row per rectangle. Filter to the group we
# want to highlight.
t$tm %>%
filter(group == "group-1",
subgroup == "subgroup-2"),
{
# Use grid.rect to add a rectangle on top of the treemap.
grid.rect(x = x0 + (w / 2),
y = y0 + (h / 2),
width = w,
height = h,
gp = gpar(col = "yellow", fill = NA, lwd = 4),
vp = "data")
}
)

igraph ggplot rStudio How can I make lines between nodes longer and add arrows? Also how can I make the legend smaller?

I have a really wordy network plot. I am basically trying to have it function as a sort of flow chart. I am trying to make its aesthetics both functional and pleasing, but I am having a difficult time. The legend's text is way too large and there is not enough space in the network for everything to be spaced out properly. Also, I want to make the background a different color.
The only solutions I have been able to find, however, require the ggnet2 package, but when I try to install the ggnet2 package, it says I cannot install that on this version of rStudio. When I tried to update my rStudio, it says that I have the most recent version of rStudio. I do not know what else to try.
Any help would be much appreciated! This is my code:
library(igraph)
library(RColorBrewer)
links <- data.frame(
source=c("Pubertal Hormones, Timing, and Development","Pubertal Hormones, Timing, and Development","Pubertal Hormones, Timing, and Development","Pubertal Hormones, Timing, and Development","Genetic Vulnerability","Genetic Vulnerability","Temperament","Temperament","Depressogenic Vulnerability","Negative Cognitive Style","Negative Cognitive Style","Objectified Body Consciousness","Objectifed Body Consciousness","Rumination","Peer Sexual Harassment","Peer Sexual Harassment"),
target=c("Genetic Vulnerability","Objectified Body Consciousness","Peer Sexual Harassment","Depressogenic Vulnerability","Temperament","Depressogenic Vulnerability","Negative Cognitive Style","Depressogenic Vulnerability","Gender Difference in Depression","Rumination","Depressogenic Vulnerability","Rumination","Depressogenic Vulnerability","Depressogenic Vulnerability","Objectified Body Consciousness","Gender Difference in Depression"),
importance=(sample(1:4, 16, replace=T))
)
V = c(links$source,
links$target) %>%
unique()
nodes <- data.frame( name=V,
carac=c(
rep("Biological Vulnerability",2),rep("Affective Vulnerability",3),rep("Cognitive Vulnerability",3),rep("Negative Life Events",2)) )
network <- graph_from_data_frame(d=links, vertices=nodes, directed=F)
coul <- brewer.pal(4, "Set3")
my_color <- coul[as.numeric(as.factor(V(network)$carac))]
plot(network, vertex.color=my_color,vertex.shape=c("vrectangle"),vertex.size=c(150),vertex.label.cex=c(0.5))
legend("bottom", legend=levels(as.factor(V(network)$carac)) , col = coul , bty = "n", pch=20 , pt.cex = 3, cex = 1, text.col=coul , horiz = TRUE, inset = c(0.1, 0.1))
With a small graph like this, you can customize the layout so that things look nicer. We'll just step through the problems one at a time. Let's start from your plot statement, but let's make it reproducible by setting the random seed.
set.seed(123)
plot(network, vertex.color=my_color,vertex.shape=c("vrectangle"),
vertex.size=c(150),vertex.label.cex=c(0.5))
The biggest problem is that the plot does not use all of the space in the graphics window. You can adjust that some with the margin parameter. When I do that, the boxes seem too big, so I will make them a bit smaller at the same time and also change the text size to match the new boxes.
set.seed(123)
LO = layout_nicely(network)
plot(network, layout=LO, margin=-0.6, vertex.color=my_color,
vertex.shape=c("vrectangle"), vertex.size=c(100),
vertex.label.cex=c(0.7))
OK, this is better, but there still are some problems. First, the box for "Pubertal Hormones, Timing, and Development" is too small. We can adjust that by using a vector of vertex sizes. When we change that, there are some other changes in the plot, so let's just make that one change first.
VS = rep(100, vcount(network))
VS[1] = 150
plot(network, layout=LO, margin=-0.7, vertex.color=my_color,
vertex.shape=c("vrectangle"), vertex.size=VS,
vertex.label.cex=c(0.7))
Next, some of the boxes overlap. We can fix those by editing the layout matrix. This matrix is just the x,y coordinates at which to plot the nodes. I just looked at the matrix and adjusted the positions a little.
LO[1,] = c(6.3,7.3)
LO[4,] = c(5.4,6.7)
LO[5,] = c(5,5.5)
LO[7,] = c(7.4,6.8)
LO[8,] = c(5.1,6.2)
LO[9,] = c(5.2,8.4)
LO[10,] = c(7,8.3)
plot(network, layout=LO, margin=-0.7, vertex.color=my_color,
vertex.shape=c("vrectangle"), vertex.size=VS,
vertex.label.cex=c(0.7))
This is pretty good. More could be done, but I think the method is clear, so I will leave any additional aesthetic adjustments of the nodes to you.
Now to finish up, you wanted to adjust the background color. You can do that (before plotting) by setting bg using par. The final version is:
par(bg="lightblue1")
plot(network, layout=LO, margin=-0.7, vertex.color=my_color,
vertex.shape=c("vrectangle"), vertex.size=VS,
vertex.label.cex=c(0.7))

Adjust edge label position in mediation diagram with DiagrammeR?

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

How to create a directed network graph with aligned nodes in R?

I would like to get something like this
A network graph with or without labels but with nodes aligned.
How can I get it?
I'm already used the packages Diagrammer and Visnetwork for other graphs, so using the same will be a bonus.
library(DiagrammeR)
library(visNetwork)
from=c("A","A","A","A","B","B","B","C","C","D")
to=c("B","C","D","E","C","D","E","D","E","E")
nodesd=c("A","B","C","D","E")
With Diagrammer:
nodes <- create_node_df( n=length(nodesd), label=nodesd, width=0.3)
edges <- create_edge_df(from = factor(from, levels=nodesd), to = factor(to, levels=nodesd), rel = "leading_to")
graph <- create_graph(nodes_df = nodes, edges_df = edges)
render_graph(graph)
I've also tried with set_node_position() but it doesn't seem to make any difference.
With Visnetwork
nodes <- data.frame(id=nodesd, label= nodesd )
edges <- data.frame(from=from, to =to, length=150)
visNetwork(nodes,edges, width="100%" , height="100%") %>%
visNodes(shape = "circle") %>% visEdges(arrows = 'to', smooth =T)
As you can see the nodes are not aligned. How can I force it to do it?
I could drag them manually but it's not something you want to do if you have many graphs, and the result is not good anyway.
I got to do it vertically with visnetwork by adding the line
%>% visHierarchicalLayout()
at the end. But it doesn't work well because many edges disappear.
If I want to get a horizontal alignement I need to add this to the nodes definition.
level = c(1,1,1,1,1)
I can't help you with DiagrammeR or visNetwork, but it is easy to do this with igraph. You just need to specify a simple layout of the nodes. You will also want to adjust the curvature of the edges. My example below has something that works, but you might adjust it to make it more artistic.
library(igraph)
EL = cbind(from, to)
g = graph_from_edgelist(EL)
L = cbind(1:5, 5:1)
CURVE = c(0,0.15, 0.3, 0.45, 0, -0.15, -0.3, 0, 0.15, 0)
plot(g, layout=L, edge.curved=CURVE)

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.

Resources