R igraph: Color nodes by degree? - r

# Erdos
par(mfrow=c(1,2))
g <- erdos.renyi.game(100, 1/100)
V(g)$size<-seq(0.05,5,0.05)
betweenness(g)
# Draw nodes and save positions
locs <- layout.fruchterman.reingold(g)
plot(g,
layout=locs,
vertex.label=NA,
main="Original",
vertex.color=degree(g))
g
vertex.color=degree(g)
did not work. Could anyone tell me how to color the vertices by "degree"?
Red (high value) to blue (low value) would be perfect.
Thanks!

A solution I found is to create a new color vector with the grey color R provides us with colors()[]. If you check colors()[] in your terminal, you can see the full list of colors that are readable by the plot.igraph() function.
You first charge your data (graph, etc.) :
edgelist <- read.csv(...)
graph <- make_graph_from_data(edgelist)
Then you create a vector of colors that corresponds to the length of your vertices list :
length(V(g)) # with a length of X vertices :
colors <- c(paste0(rep("grey",X),seq(X,1)))
Finally, you plot it with the attribute vertex.color :
plot(g,vertex.color=colors[degree(graph)])
However, one can only use this little trick for graph with less than 100 values in degree(graph)...

Related

how can I extract a sublayout to match a subgraph in R

I'm using igraph in R, trying to extract a subgraph that comprises only the largest cliques in a graph. I want to plot the graph and the subgraph (1) without moving the vertices and (2) while maintaining numbering. I can't seem to make it work. I tried storing the layout coordinates directly in the vertices but plot seems to rescale things. Setting rescale=FALSE didn't work either. Here's what I have, first plotting the random graph, then highlighting the largest cliques, and finally displaying only the largest cliques:
# plot random graph
g <- sample_gnp(n=30, p=.1)
l=layout_with_fr(g)
V(g)$x <- l[,1]
V(g)$y <- l[,2]
V(g)$id <- 1:vcount(g)
plot(g,vertex.size=6,vertex.label.dist=1,vertex.label=V(g)$id,main="a random network",sub="where are the cliques?")
# highlight largest cliques
lc=unlist(largest_cliques(g))
vcol <- rep("grey80", vcount(g))
vcol[unlist(lc)] <- "gold"
plot(g, vertex.size=6,vertex.color=vcol,vertex.label.dist=1,vertex.label=V(g)$id,main="here they are!",
layout=l)
# plot only the largest cliques, without changing position or vertex numbers
sg = induced_subgraph(g,lc)
sl = cbind(V(sg)$x,V(sg)$y)
plot(sg,vertex.size=6,vertex.label.dist=1,vertex.label=V(sg)$id,vertex.color="gold",
layout=sl)
First of all, you did not set the random seed, so each time you run this code you will get a different graph and layout. I am setting the seed for reproducibility.
# plot random graph
set.seed(2021)
g <- sample_gnp(n=30, p=.1)
l=layout_with_fr(g)
V(g)$x <- l[,1]
V(g)$y <- l[,2]
V(g)$id <- 1:vcount(g)
# highlight largest cliques
lc=unlist(largest_cliques(g))
vcol <- rep("grey80", vcount(g))
vcol[unlist(lc)] <- "gold"
There are other ways to do this, but I will do it using rescale=F.
When you do that, you have to adjust xlim and ylim to the ranges of the layout. Also, it changes the scale, so you need to change the vertex size.
Putting all of that together, I get:
Rx =range(l[,1])
Ry =range(l[,2])
par(mfrow=c(1,2))
plot(g, vertex.size=45,vertex.color=vcol,vertex.label.dist=1,
vertex.label=V(g)$id,main="here they are!", layout=l,
rescale=F, xlim=Rx, ylim=Ry)
# plot only the largest cliques, without changing position or vertex numbers
sg = induced_subgraph(g,lc)
sl = cbind(V(sg)$x,V(sg)$y)
plot(sg,vertex.size=45, vertex.label.dist=1,vertex.label=V(sg)$id,vertex.color="gold",
layout=sl, rescale=F, xlim=Rx, ylim=Ry, main="Unmoved")
you can use set-vertex_attr to set the name attribute for graph g, and then subset the layout lc like below
# plot random graph
set.seed(2021)
g <- sample_gnp(n = 30, p = .1)
l <- layout_with_fr(g)
# highlight largest cliques
lc <- unlist(largest_cliques(g))
g %>%
set_vertex_attr(name = "name", value = seq(vcount(.))) %>%
induced.subgraph(lc) %>%
plot(layout = l[as.integer(names(V(.))), ], vertex.color = "gold")
and you will get

different vertex shapes for each vertex of decomposed graph

I have a very large bipartite network model that I created from 5 million lines of a dataset. I decompose my network model because I can not draw a graph of this size. Now all I need is to plot the decompose graphics one by one. There is no problem with that. But I want to draw the graph with a shape according to the attributes of each node. For example, I want a square for the "A" attributes on my graph G, and a triangle for the "B" attributes. In addition to this I want to add vertex labels by attributes. Here is my codes to plot first component of graph after creating bipartite G and its work:
components <- decompose(G)
plot(components[[1]])
I tried something like this to adding labels and changing vertex shapes according to graph attributes but it didn't work:
plot(components[[1]], vertex.label= V(G)$attributes,
vertex.shape=c("square", "triangle"))
Does anyone can help me, I'm stuck. Thank you so much!
the components function returns a list of vertices which make up a component. So you need to traverse the list, create a subgraph and plot. As for plotting attributes you need to provide a reproducible example for us to help.
library(igraph)
set.seed(8675309)
g <- sample_gnp(200, p = 0.01)
V(g)$name <- paste0("Node", 1:vcount(g))
V(g)$shape <- sample(c("circle","square"), vcount(g), replace = T)
clu <- components(g)
grps <- groups(clu)
lapply(grps, function(x) plot(induced_subgraph(g, x)))

How to set node color different in one cluster using R {igraph}?

I have a set of data of city, each city have a majority etnic. Let's say
City Etnic
A x
B y
C z
etc. I make a graph of social network where the node represent the name of the city, and the link is the neighborhood of the city with another city. I'm using package igraph in R.
After that I do graph partitioning to find it's community. Let's say it came with 4 communities. And in one community, there was multiple etnic. The node color represent the majority etnic.
The problem is, the node color of graph is following the community. This is my code:
#make a graph from data frame
g=graph.data.frame(link, directed=T, vertices=node)
#clustering/graph partitioning
clust=cluster_optimal(g)
#node color
V(g)$color <- ifelse(V(g)$etnic == "x", "red",ifelse(V(g)$etnic =="y", "blue", "green")
plot(clust, g, edge.arrow.size=.15, edge.curved=0, vertex.frame.color="black",
vertex.label=V(g)$city, vertex.label.color="black",
vertex.label.cex=.8,layout=l)
The question is how I make the node color represent the color of etnic I declare?
If you still want to plot the grouping of the clustering algorithm, you can use the mark.groups argument.
I learned about this in Randi Griffin's great blogpost: http://www.randigriffin.com/2017/04/26/primate-social-networks-in-igraph.html
Here is a reproducible example:
library(igraph)
# Assume we examine (fictive) train connections of 4 countries: Switzerland, Italy, France, Spain
# in the Swiss cities "Genf" and "Lugano" there are different languages/ethnicities
#construct the graph
g <- graph (c( "Zurich","Bern","Zurich","Bern", "Genf","Bern","Lugano","Zurich",
"Genf","Zurich","Lugano","Bern",
"Rome","Venice","Rome","Milano","Venice","Milano",
"Marseille","Lyon","Marseille","Toulouse","Lyon","Toulouse",
"Barcelona","Saragosa","Barcelona","Valencia","Saragosa","Valencia",
"Milano","Lugano","Genf","Lyon","Milano","Marseille","Marseille","Barcelona"
))
#set major language/ethnicities
V(g)$etnic <- c("Swiss", "Swiss","French","Italian", #for Genf and Lugano respectively!
"Italian","Italian","Italian",
"French","French","French",
"Spanish","Spanish","Spanish")
V(g)$color <- ifelse(V(g)$etnic == "Italian", "#61D04F", ifelse(V(g)$etnic =="French", "#2297E6", ifelse(V(g)$etnic == "Spanish","#F5C710","red")))
#when we simply plot this graph, everything looks good
plot(g, vertex.label.color="black", vertex.label.dist=1.8, edge.arrow.size=.5,
vertex.color = V(g)$color)
# now let's see, whether the clustering finds the four countries
clust <- cluster_optimal(g)
#but when we plot this, the clustered graph loses the color of the vertices
plot(clust, g, edge.arrow.size=.15, edge.curved=0, vertex.frame.color="black",
vertex.label=V(g)$city, vertex.label.color="black",
vertex.label.cex=.8, layout=layout_with_dh(g))
#there are 4 communities, but we want to color Lugano and Genf differently as they speak other languages
# use the mark.groups argument
plot(g, mark.groups=communities(clust),
edge.arrow.size=.15, edge.curved=0, vertex.frame.color="black",
vertex.label=V(g)$city, vertex.label.color="black",
vertex.label.cex=.8, layout=layout_with_dh(g))
# also check out the other arguments for the grouping:
# mark.shape, mark.border, mark.col and mark.expand
When you are plotting the clustering object (i.e. clust), you are explicitly asking igraph to color the vertices based on their cluster membership, so it will ignore the color vertex attribute. Plot only the graph instead:
plot(g, edge.arrow.size=.15, edge.curved=0, ...)

How to scale edge colors in igraph?

I'm plotting a graph with igraph and I would like the edges to have different colors depending on the strength of the connections they represent. I could set the colors but I cannot relate them to the values of the connections' strength.
My current code is the following:
library(igraph)
library(raster)
library(ggplot2)
library(statnet)
library(qgraph)
connectivityMatrix <- as.matrix(read.table(file=myFile,sep='')))
coordinates <- as.matrix(read.table(file=coordinatesFile))
connectivityMatrix<-connectivityMatrix[1:833,1:833]
CM<-connectivityMatrix[subsetX,subsetY]
COORD<-coordinates[subset,]
net <- as.network(CM, matrix.type = "adjacency", directed = TRUE)
minX<-min(coordinates[,1])
maxX<-max(coordinates[,1])
minY<-min(coordinates[,2])
maxY<-max(coordinates[,2])
p<-plot(net, coord=COORD,xlim=c(minX,maxX),ylim=c(minY,maxY),edge.col=c('red','yellow','cyan','blue'),object.scale=0.005, vertex.col='dimgrey',edge.lwd=1)
In the code above is there a way to relate the colors specified using edge.col to the range of values they represent in the CM? This way, the edges corresponding to the value 0-x1 in the connectivity matrix would be plotted in red, x1-x2 in 'yellow',.... and x3-x4 in blue. x1, x2, x3 being the range limits and x4 being the maximum of the CM.
Does anyone have an idea on how to do it? Would it be possible to add a legend including the edges' color and the ranges of values they represent?
You can use colorRamp as a scaling function. see the code below for example.
library(igraph)
#Create a random weighted graph
g = erdos.renyi.game(10,0.5)
E(g)$weight = runif(ecount(g))
#Color scaling function
c_scale <- colorRamp(c('red','yellow','cyan','blue'))
#Applying the color scale to edge weights.
#rgb method is to convert colors to a character vector.
E(g)$color = apply(c_scale(E(g)$weight), 1, function(x) rgb(x[1]/255,x[2]/255,x[3]/255) )
#plot using igraph
plot.igraph(g)

How to plot directed acyclic lattice graph in R

I need to plot directed acyclic lattice graph of size m x n, similar as in this picture, but without edges on the contour and without vertexes on the corners:
Is this possible to do with graph.lattice function? If yes, how to set such vertexes' labels (i.e. (x,y) format, not just an integer number) and remove mentioned edges and vertexes? Moreover, is it possible to plot graph in such position (as in a picture) without using tkplot function and rotating it then?
I am not exactly sure what you mean by 'without edges on the contour', but here are some points:
Read ?igraph.plotting for the complete list of plotting parameters.
If you don't want the frame on the vertices, set vertex.frame.color to the same value as vertex.color.
Use layout.grid, see ?layout.grid.
Use vertex.label to set the labels.
If you want to omit some edges, then delete them, or set their width to zero or their color to background color.
If you want to omit some vertices, then attach the coordinates calculated by layout.grid as vertex attributes, and then remove the vertices from the graph.
Something like this could work:
g <- graph.lattice( c(5,5) )
lay <- layout.grid(g)
V(g)$x <- lay[,1]
V(g)$y <- lay[,2]
V(g)$color <- V(g)$frame.color <- "darkolivegreen"
V(g)$label.color <- "lightgrey"
V(g)$label <- paste(V(g)$x+1, V(g)$y+1, sep=",")
To remove the edges, you can select them based on the coordinates of the vertices:
torem <- c(E(g)[ V(g)[x==0] %--% V(g)[x==0] ],
E(g)[ V(g)[y==0] %--% V(g)[y==0] ],
E(g)[ V(g)[x==4] %--% V(g)[x==4] ],
E(g)[ V(g)[y==4] %--% V(g)[y==4] ])
g2 <- delete.edges(g, torem)
And then remove the vertices and plot:
g3 <- delete.vertices(g2, V(g2)[ x %in% c(0,4) & y %in% c(0,4) ])
plot(g3, layout=cbind(V(g3)$x, V(g3)$y))

Resources