I have an igraph plot that is geographically laid out based on its latitude and longitude coordinates. I now want to hide certain points from one time period, while preserving the layout of the graph. I would therefore not like to delete the vertices from the network, but merely make them invisible in this particular plot rendering, conditional on a vertex attribute. Furthermore, the color attribute is already set to capture another variable, so I cannot use that to hide the points.
My plot is generated according to the following code:
lo <- layout.norm(as.matrix(g[, c("longitude","latitude")]))
plot.igraph(g, layout=lo, vertex.label=NA,rescale=T, vertex.size = 4)
The time attribute is a numerical variable stored in V(g)$period
Is there code I can put within the plot.igraph function to hide vertices for which V(g)$period == 1?
Update.
Building upon Szabolcs's answer.
library(igraph)
## reproducible example
g <- make_graph("Zachary")
V(g)$name <- V(g)
set.seed(10)
lyt <- layout_with_drl(g)
V(g)$x <- lyt[,1]
V(g)$y <- lyt[,2]
plot(g)
del_vs <- c(4, 8, 9, 19, 24, 33)
dev.new(); plot(g - del_vs, main = paste("Zachary minus", toString(del_vs)))
Try invisible inkt, e.g. print hidden objects in background color.
Or try this.
library(igraph)
## reproducible example.
g <- make_graph("Zachary")
V(g)$name <- V(g)
set.seed(10)
lyt <- layout_with_drl(g)
plot(g, layout=lyt)
## delete vertices and preserve layout.
del_vs <- c(9, 19, 24, 33)
g2 <- g - del_vs
g2$main <- paste("Zachary minus", toString(del_vs))
g2$layout <- matrix(lyt[-del_vs,], ncol=2)
dev.new(); plot(g2)
See also:
Looking to save coordinates/layout to make temporal networks in Igraph with DRL
.
You can store the coordinates in the x and y vertex attributes. Then they will be used by plot automatically, and they will be preserved when you delete vertices.
For example:
g<-make_ring(4)
V(g)$x <- c(0,0,1,1)
V(g)$y <- c(0,1,0,1)
plot(g)
plot(delete_vertices(g,1))
Related
I am trying to subset an igraph plot to display certain nodes based on a given vertex attribute. I have to subset them in the plot output to preserve the layout for the vertices. My code is the following:
plot.igraph(graph, layout=lo, vertex.label=NA, rescale=T, vertex.size = 4) %>%
tidygraph::activate(nodes) %>%
filter(period == 1)
But I receive the following error:
Error in UseMethod("activate") :
no applicable method for 'activate' applied to an object of class "NULL"
How can I subset the graph based on the vertex attribute "V(graph)$period", maintaining the vertices' layout?
Observe that class(plot(graph)) returns NULL.
Update, calculate subset as follows.
## Random example.
set.seed(20)
g <- make_ring(20)
V(g)$period <- sample(2, vcount(g), replace=TRUE)
V(g)$name <- V(g)
## Calculate subset of vertices
## and plot subgraph.
vvv <- V(g)[which(V(g)$period==1)]
g2 <- subgraph(g, vvv)
plot(g2)
I am building a phylogenetic tree using data from NCBI taxonomy. The tree is quite simple, its aims is to show the relationship among a few Arthropods.
The problem is the tree looks very small and I can't seem to make its branches longer. I would also like to color some nodes (Ex: Pancrustaceans) but I don't know how to do this using ape.
Thanks for any help!
library(treeio)
library(ape)
treeText <- readLines('phyliptree.phy')
treeText <- paste0(treeText, collapse="")
tree <- read.tree(text = treeText) ## load tree
distMat <- cophenetic(tree) ## generate dist matrix
plot(tree, use.edge.length = TRUE,show.node.label = T, edge.width = 2, label.offset = 0.75, type = "cladogram", cex = 1, lwd=2)
Here are some pointers using the ape package. I am using a random tree as we don't have access to yours, but these examples should be easily adaptable to your problem. If your provide a reproducible example of a specific question, I could take another look.
First me make a random tree, add some species names, and plot it to show the numbers of nodes (both terminal and internal)
library(ape)
set.seed(123)
Tree <- rtree(10)
Tree$tip.label <- paste("Species", 1:10, sep="_")
plot.phylo(Tree)
nodelabels() # blue
tiplabels() # yellow
edgelabels() # green
Then, to color any node or edge of the tree, we can create a vector of colors and provide it to the appropriate *labels() function.
# using numbers for colors
node_colors <- rep(5:6, each=5)[1:9] # 9 internal nodes
edge_colors <- rep(3:4, each=9) # 18 branches
tip_colors <- rep(c(11,12,13), 4)
# plot:
plot.phylo(Tree, edge.color = edge_colors, tip.color = tip_colors)
nodelabels(pch = 21, bg = node_colors, cex=2)
To label just one node and the clade descending from it, we could do:
Nnode(Tree)
node_colors <- rep(NA, 9)
node_colors[7] <- "green"
node_shape <- ifelse(is.na(node_colors), NA, 21)
edge_colors <- rep("black", 18)
edge_colors[13:18] <- "green"
plot(Tree, edge.color = edge_colors, edge.width = 2, label.offset = .1)
nodelabels(pch=node_shape, bg=node_colors, cex=2)
Without your tree, it is harder to tell how to adjust the branches. One way is to reduce the size of the tip labels, so they take up less space. Another way might be to play around when saving the png or pdf.
There are other ways of doing these embellishments of trees, including the ggtree package.
I have a file csv including edge list of graph. After implementing CONGA
(Clustering Overlap Girven-NewMan alorithm), result is a list of vertices of each group.
I don't know how to plot it so that each group has different color in graph by R.
I can plot graph with edge list in R, but I don't know how to mark vertices in each group.
Input: edge list file and list of vertices in each group.
Output: graph with different color for each group.
output nearly like this
My English isn't good. Thanks for your support.
You plot colors using $color of vertices. Try to assign a color like V(g)$color <- 'green'.
It is better if you give us some code.
You say you get a list of your group-members. Convert the list to a vector, and sign a new color to each unique group-member value. I wrote this example code. I think it shows what you're after.
library(igraph)
get_a_random_network <- function() {
# EN: Function to get some random data to use as an example
g <- erdos.renyi.game(100, 60, type="gnm", directed=F, loops=FALSE)
g <- g %>% delete_vertices( V(g)[degree(g)==0] )
(g)
}
# Get sample data
g <- get_a_random_network()
# Use a cluster algorythm to determine groups. You said you had a list. I use this to generate example data.
groups <- cluster_fast_greedy(g)
# Look at the vertecies
(V(g))
# Look at what groups they belong to:
(groups$membership)
# Here you write that you have "list of vertices of each group". You don't
# give us code, but I assume that you have data that looks like this:
CONGA_list <- lapply(1:max(groups$membership),function(x) V(g)[groups$membership ==x])
(CONGA_list)
# This is where you should really have provided a code example.
# You could convert a list like CONGA_list to a vector like this:
membership_groups <- rep(0, length(V(g)))
for(x in 1:length(CONGA_list)){
membership_groups[as.vector(CONGA_list[[x]])] <- x
}
(membership_groups == groups$membership)
# You give color to your network by first telling each vector which group it belongs to
V(g)$membership <- groups$membership
# Then we asign a color. I use a vector of R-colors which I get like this...
colors = grDevices::colors()[grep('gr(a|e)y', grDevices::colors(), invert = T)]
# ... and then I sample from them to give each vertecy a color.
colors <- sample(colors, max(V(g)$membership))
V(g)$color <- colors[V(g)$membership]
(V(g)$color)
# The plot will work with the colors in V(g)$color
plot(g, vertex.size=7, vertex.label=NA)
Good luck
I'm trying to plot a temporal social network in R. My approach is to create a master graph and layout for all nodes. Then, I will subset the graph based on a series of vertex id's. However, when I do this and layout the graph, I get completely different node locations. I think I'm either subsetting the layout matrix incorrectly. I can't locate where my issue is because I've done some smaller matrix subsets and everything seems to work fine.
I have some example code and an image of the issue in the network plots.
library(igraph)
# make graph
g <- barabasi.game(25)
# make graph and set some aestetics
set.seed(123)
l <- layout_nicely(g)
V(g)$size <- rescale(degree(g), c(5, 20))
V(g)$shape <- 'none'
V(g)$label.cex <- .75
V(g)$label.color <- 'black'
E(g)$arrow.size = .1
# plot graph
dev.off()
par(mfrow = c(1,2),
mar = c(1,1,5,1))
plot(g, layout = l,
main = 'Entire\ngraph')
# use index & induced subgraph
v_ids <- sample(1:25, 15, F)
sub_l <- l[v_ids, c(1,2)]
sub_g <- induced_subgraph(g, v_ids)
# plot second graph
plot(sub_g, layout = sub_l,
main = 'Sub\ngraph')
The vertices in the second plot should match layout of those in the first.
Unfortunately, you set the random seed after you generated the graph,
so we cannot exactly reproduce your result. I will use the same code but
with set.seed before the graph generation. This makes the result look
different than yours, but will be reproducible.
When I run your code, I do not see exactly the same problem as you are
showing.
Your code (with set.seed moved and scales added)
library(igraph)
library(scales) # for rescale function
# make graph
set.seed(123)
g <- barabasi.game(25)
# make graph and set some aestetics
l <- layout_nicely(g)
V(g)$size <- rescale(degree(g), c(5, 20))
V(g)$shape <- 'none'
V(g)$label.cex <- .75
V(g)$label.color <- 'black'
E(g)$arrow.size = .1
## V(g)$names = 1:25
# plot graph
dev.off()
par(mfrow = c(1,2),
mar = c(1,1,5,1))
plot(g, layout = l,
main = 'Entire\ngraph')
# use index & induced subgraph
v_ids <- sort(sample(1:25, 15, F))
sub_l <- l[v_ids, c(1,2)]
sub_g <- induced_subgraph(g, v_ids)
# plot second graph
plot(sub_g, layout = sub_l,
main = 'Sub\ngraph', vertex.label=V(sub_g)$names)
When I run your code, both graphs have nodes in the same
positions. That is not what I see in the graph in your question.
I suggest that you run just this code and see if you don't get
the same result (nodes in the same positions in both graphs).
The only difference between the two graphs in my version is the
node labels. When you take the subgraph, it renumbers the nodes
from 1 to 15 so the labels on the nodes disagree. You can fix
this by storing the node labels in the graph before taking the
subgraph. Specifically, add V(g)$names = 1:25 immediately after
your statement E(g)$arrow.size = .1. Then run the whole thing
again, starting at set.seed(123). This will preserve the
original numbering as the node labels.
The graph looks slightly different because the new, sub-graph
does not take up all of the space and so is stretched to use
up the empty space.
Possible fast way around: draw the same graph, but color nodes and vertices that you dont need in color of your background. Depending on your purposes it can suit you.
New to igraph. I would like to have vertex colours be defined by another parameter, preferably continuous colours (think heatmap or grayscale).
clusters_only <- as.character(temp_df$SeqID)
v_names <- data.frame(c(unique_order, as.character(temp_df$SeqID)))
graph_order <- graph.data.frame(temp_df, directed = FALSE, vertices = v_names)
V(graph_order)[clusters_only]$size <- ? #continuous colour based on variable in temp_df
Any ideas?
Much appreciated.
You can use the color attribute of vertices to specify the vertex colors. It may be a string (containing a color name known to R) or a numeric value, in which case the color will be selected from the current palette. E.g.:
library(igraph)
g <- grg.game(100, 0.2)
V(g)$color <- 1:100
palette(gray.colors(100))
plot(g)
Alternatively, you may specify the colors as the argument of plot instead of assigning them to a vertex attribute:
plot(g, vertex.color <- 1:100)
I had better luck with this syntax:
R> library(igraph)
R> g <- grg.game(100, 0.2)
R> V(g)$color <- 1:100
R> g$palette <- grey.colors(100) #### updated this line
R> plot(g)
Maybe the grammar has changed since the original answer?