I have a igraph network object with a number of edge attributes. One edge attribute classifies type of network according to number (e.g. 1 = friendship, 2 = advice). I want to plot each type of network separately. However, I do not want to create separate sub-graphs. I want to maintain the same layout for all network types, using just one igraph network object. How to do this is not obvious to me in the iGraph documentation. Can somebody help me here?
if you plot the graph twice and set the same set.seed() before each plot, the layout should be the same. Then you could make edges transparent/visible depending on the edges you want to show.
I believe there is no direct way to do that in igraph. And that makes sense because those are attributes; i.e., something additional rather than a standard way to specify an edge type. Hence, I think one good option is simply altering the set of edges while plotting a graph as in the following example:
library(igraph)
g <- make_ring(10) %>%
set_edge_attr("weight", value = 1:10) %>%
set_edge_attr("color", value = "red")
plot(g %>% delete_edges(which(edge_attr(g)$weight > 5)))
plot(g %>% delete_edges(which(edge_attr(g)$weight <= 5)))
Related
I am interested in visualizing the results of a hierarchical cluster analysis. Is it possible to use a dendrogram to display the names or labels of clusters (and subclusters) without displaying the original cases that went into the cluster analysis?
For example, this code applies a hierarchical cluster analysis to the mtcars dataset.
data("mtcars")
clust <- hclust(get_dist(mtcars, method = "pearson"), method = "complete")
plot(clust)
Let's say I cut the tree at 4 clusters and rename the clusters "sedan", "truck", "sportscar", and "van" (totally arbitrary labels).
clust1 <- cutree(clust,4)
clust1 <- dplyr::recode(clust1,
'1'='sedan',
'2'='truck',
'3'='sportscar',
'4'='van')
Is it possible to display a dendrogram which shows these four labels as the nodes on the bottom of the tree, suppressing the names of the original car names?
I am also interested in displaying subclusters within clusters in a similar way, but that may be outside the scope of this question. Bonus points if you can also give a suggestion for how to display subclusters within clusters in a dendrogram while suppressing the names of the original cases! :)
Thank you in advance!
Yes, you can do this. I do not understand your get_dist so I will illustrate using the ordinary distance dist.
data("mtcars")
clust <- hclust(dist(mtcars), method = "complete")
To cut off and display just the top of the tree, change it to a dendrogram and use upper. But you need to know what to height to cut it at. That is in the structure clust.
tail(clust$height)
[1] 113.3023 134.8119 141.7044 214.9367 261.8499 425.3447
Since you want four branches, you can cut at any height between the third and fourth heights (from the end). I will use 213.
MTC_Dend = as.dendrogram(clust)
TreeTop = cut(MTC_Dend, h = 213)$upper
You can get the basic plot now with plot(TreeTop), but it won't have the labels that you want. To change the labels, use the package dendextend which offers a tool specifically to change the labels.
library("dendextend")
labels(TreeTop) = c('sedan','truck', 'sportscar', 'van')
plot(TreeTop)
I am trying to visualize some networks using the ggraph package. My network has two different types of edges, A and B, which have different scales. I'd like to color the edges by type (which I've done) and also modulate their opacity by the value. However, since all the edges are displayed together and since A and B have different scales, using aes(alpha=value) uses the entire scale over both A and B, so all the edges with the smaller scale (here A) are practically invisible. How can I separate the alpha scales for A and B so that the alpha corresponds to their internal scales? (ie, alpha=1 when an A edge is at max A and a B edge is at max B)
I've included a small example below:
library(ggplot2)
library(igraph)
library(ggraph)
nodes <- data.frame(id=seq(1,5),label=c('a','b','c','d','e'))
edges <- data.frame(from=c(3,3,4,1,5,3,4,5),
to= c(2,4,5,5,3,4,5,1),
type=c('A','A','A','A','A','B','B','B'),
value=c(1,.2,.5,.3,1,5,12,8))
net <- graph_from_data_frame(d=edges,vertices=nodes,directed=T)
ggraph(net,layout='stress') +
geom_edge_fan(aes(color=type,alpha=value)) +
geom_node_label(aes(label=label),size=5)
This is what the graph currently looks like:
And I want something that looks like this:
Ideally I'd be able to do this in R and not do a convoluted editing process in GIMP.
I was hoping this would be possible with set_scale_edge_alpha, but I can't find the solution anywhere. I saw from here that this can be done with ggnewscale, but this seems to require drawing two separate objects, and it also doesn't seem like there is a function for specifically changing edge aesthetics. Is there a simple way to do this without drawing two overlapping graphs?
Thanks!
It would probably be better just to rescale the values yourself before plotting. You can scale the values to a 0-1 scale within each group
edges <- edges %>%
group_by(type) %>%
mutate(value = scales::rescale(value))
I'm experimenting with the outstanding ggraph library to depict some really-hard to depict interrelationships for a scientific work. Specifically, I want to show SNP-SNP interactions in a genetic locus. It would be very nice if I plotted the interactions as curved nodes of a graph, where the SNPs are positioned in a linear fashion according to their genetic positions. The geom_edge_arc() aesthetics from the ggraph library would be ideal. However, I cannot put the nodes in an order according to the positions.
Here is an example
library(igraph)
library(tidyverse)
library(ggraph)
set.seed(10)
nodes <- tibble(nodes = paste("SNP",seq(1:10)), pos = sample(c(10000:20000),10))
edges <- expand.grid(nodes$nodes,nodes$nodes) %>%
mutate(interaction = rnorm(100)) %>%
filter(abs(interaction)>1)
gr <- graph_from_data_frame(edges, vertices = nodes)
ggraph(gr, 'linear', circular=F) +
geom_edge_arc(aes(edge_width=interaction))
The nodes are evenly spaced here, as "factors". However, I wanted to place them on the x coordinate as specified by the pos variable (which in turn becomes an attribute of the nodes). Adding + geom_node_point(aes(x=pos))to the ggplot object doesn't result in a correct rendering. I could probably do the plot with "basic" ipgraph too, but I like ggraph and ggplot2, and it would be an elegant and easy way to plot with this.
Kind regards, and thanks in advance,
Robert
Not sure if this is still relevant, but there are two ways to solve this.
As noted by #axeman, you can use the manual layout, and basically pass the x and y coordinates to it:
ggraph(gr,
layout = 'manual',
node.position = data_frame(y = rep(0, length(nodes$pos)), x = nodes$pos)) +
geom_edge_arc(aes(edge_width=interaction))
The othe way is to overrride the x aes inside geom_edge_arc. To be able to pass a node attribute to an aes we need to use geom_edge_arc2:
ggraph(gr, 'linear', circular=F) +
geom_edge_arc2(aes(edge_width=interaction, x = node.pos))
Created on 2018-05-30 by the reprex package (v0.2.0).
I am using the R package adegenet to plot the neighbor-joining tree.
In my file I have 20,000 columns and 500 rows. Rows correspond to individuals. My first column is Population ID and second column is Individual ID. Columns contain values 0,1 & 2. I am able to plot a tree in one color, but depending upon the population I want every cluster to be a different color.
This is what I did, If "dat" is my data file,then
D<-dist(as.matrix(dat))
tre<-nj(D)
plot(tre, type = "unr", show.tip.lab = TRUE, cex=0.3, font=1, edge.col="Blue")
If I try edge.col=c("red","green","blue") I run into following error :
Error in if (use.edge.length) unrooted.xy(Ntip, Nnode, z$edge, z$edge.length, :
argument is not interpretable as logical
Ill appreciate any help!
Your example should be reproducible, so that it would be easier to help and reproduce your problem. See this post for more details. I'm trying with iris and it works like a charm. By the way, I think adegenet is not required here, the plot is actually a plot.phylo from the package ape), and all other functions are either built-in or from ape).
Documentation (?plot.phylo) says:
edge.col a vector of mode character giving the colours used to draw the branches of the plotted phylogeny. These are taken to be in the same order than the component edge of phy. If fewer colours are given than the length of edge, then the colours are recycled.
ape preserves the order or rows, and you can use a factor to index you vector of colors, so a reproducible example using iris could be:
library(ape)
D <-dist(as.matrix(iris[, 1:4]))
tree <- nj(D)
plot(tree, type = "unr", show.tip.lab = TRUE, cex=0.3, font=1,
edge.col=c("red","green","blue")[iris$Species])
Is that what you want?
I'm making a network plot in R using iGraph. I first plot it using tkplot() so that I can manually reposition some of the nodes. Then I capture the new coordinates and then insert those in the plot function to replot the graph along with additional adjustments (changing the opacity of the nodes).
The problem is that even when using the tkplot.coords coordinates, the second graph doesn't look like the tkplot. Instead, some of the arrow heads appear in the middle of the edge rather than at the end, and the nodes are tightly clustered and overlapping, even though that isn't the case with the tkplot. Any suggestions for how I can get the plot() function to exactly mimic the plot produced using tkplot()?
I am using R Studio, so I am wondering if there is a conversion issue with that.
My simplified code is as follows:
Net1 <- graph.data.frame(myedgedata, vertices=nodeslist, directed=TRUE)
g <- graph.adjacency(get.adjacency(Net1), weighted = TRUE)
E(g)$weight <- E(g)$weight+1
tkplot(g)
coords <- tkplot.getcoords(1)
plot(g, edge.width=E(g)$weight, vertex.color = adjustcolor(nodeslist$colors, alpha=.5), layout=coords)