Get a graph from all vertex with incident edges R igraph - r

I would like to obtain a subgraph from a graph, composed of all the vertex with incident edges starting from some vertices, and following the edges until there are no more incident edges. With the following code I only get the first neighbours
g <- graph_from_literal( 1 -+ 4 -+ 5 -+ 8,2 -+ 5 , 3-+6-+7, 4+-3, 4-+8, 5 -+9, simplify = FALSE)
adjacent_vertices(g, V(g)[c("7","9")], mode="in")
I know that I should make some kind of loop but adjacent_vertices returns a list and I can't figure out how to make it.
For this example, the result should be
graph_from_literal( 1 -+ 4 -+ 5 ,2 -+ 5 , 3-+6-+7, 4+-3, 5 -+9, simplify = FALSE)

make_ego_graph can be used to find subgraphs in the neighbourhood of specific nodes.
You can search through the full graph by setting the order parameter in
the function make_ego_graph.
Example
library(igraph)
# Your graph
g = graph_from_literal( 1 -+ 4 -+ 5 -+ 8, 2 -+ 5 , 3-+6-+7, 4+-3, 4-+8, 5 -+9,
simplify = FALSE)
# Set the order equal to the number of nodes in the graph
sg = make_ego_graph(g, nodes = V(g)[c("7","9")], order=length(V(g)), mode="in")
# This returns two subgraphs as node 3 has no inward edges and so the graph 3->6->7
# is unconnected to the other nodes. You can join the subgraphs by using
do.call(union, sg)

Related

R Igraph subgraph given node index and number of nodes to include in the graph

I want to plot a portion of a graph according to a specific node and ideally a distance from that node or a number of nodes as part of the sub graph.
The data.frame that I am graphing is as follows:
Column 1 Column 2 Sequence
A B 1
A D 2
D B 3
Z E 4
E D 5
this is the code:
network <- graph.data.frame(data_to_graph[,c(1,2)])
subnetwork <- induced.subgraph(network, vids = 30, impl = 'copy_and_delete', eids = c(5,6,7,8,9,10,11,12,13,14,15))
plot(subnetwork)
I would like, by specifying an element of column 1 to plot a graph at a certain distance from that node.
Thanks
Dario.
This is the answer:
distan <- 3
node <- "node name"
subnetwork <- induced.subgraph(network, vids = as.vector(unlist(neighborhood(network, distan, nodes = node, mode = 'all'))))
plot.igraph(subnetwork, vertex.size=10)

Combine community detection with connected components grouping igraph R

I use igraph cluster_spinglass to detect compartments (communities) in a directed network but that only works for connected components
g <- graph_from_literal( 1 -+ 4 -+ 7,2 -+ 5 -+ 9, 4+-5,
3 -+ 6,5 -+8, 8-+ 9, simplify = FALSE)
m<-cluster_spinglass(g)
Gives an error, the solution is to extract the connected component
dg <- components(g)
g1 <- induced_subgraph(g, which(dg$membership == which.max(dg$csize)))
m<-cluster_spinglass(g1)
I get the memberships of the nodes (vertices) with
m$membership
But here I don't have all the nodes of the original network g, I would like to add another group with these nodes so I have all the original nodes clasified in different groups.
You can just transfer this into your original graph g.
In your example, I think that you just want the vertices in the
other connected component to be another community, it suffices to assign all nodes in the second component to group 3.
V(g)$membership = 3
V(g)[V(g1)$name]$membership = m$membership
V(g)$membership
[1] 1 1 1 2 2 2 3 3 2
But in a more general example, there might be multiple components and those components might break up into multiple communities.
To cover that, you can loop through all components, compute the communities and then transfer those back to the original graph.
V(g)$membership = 0
for(comp in unique(dg$membership)) {
g1 <- induced_subgraph(g, which(dg$membership == comp))
m<-cluster_spinglass(g1)
V(g)[V(g1)$name]$membership = m$membership + max(V(g)$membership)
}
V(g)$membership
[1] 1 1 1 2 2 2 3 3 2

Find number of mutual edges of vertices in igraph in R

This should be straightforward, but I want to obtain the number of mutual edges associated with all the vertices in my graph:
library(igraph)
ed <- data.frame(from = c(1,1,2,3,3), to = c(2,3,1,1,2))
ver <- data.frame(id = 1:3)
gr <- graph_from_data_frame(d = ed,vertices = ver, directed = T)
plot(gr)
I know I can use which_mutual for edges, but is there an equivalent command for getting something like this:
# vertex edges no_mutual
# 1 2 2
# 2 1 1
# 3 2 1
UDPATE: Corrected inconsistencies in output table as pointed out by emilliman5
Here's a one-liner solution:
> table(unlist(strsplit(attr(E(gr)[which_mutual(gr)],"vnames"),"\\|")))/2
1 2 3
2 1 1
It relies on getting the vertex names for each edge in an edgelist as the "vnames" attribute being a "|"-separated string. It then splits on that, then that gives you a table of all vertexes in mutual edges, and each one appears twice per edge so divide by two.
If there's a less hacky way of getting vertex names from an edgelist, I'm sure Gabor knows it.
Here's that trick in more detail:
For your graph gr:
> E(gr)
+ 5/5 edges (vertex names):
[1] 1->2 1->3 2->1 3->1 3->2
You can get vertexes for edges thus:
> attr(E(gr),"vnames")
[1] "1|2" "1|3" "2|1" "3|1" "3|2"
So my one-liner subsets that edge list my the mutuality criterion, then manipulates the strings.
I am not sure how well this will scale, but it gets the job done. Your expected table has some inconsistencies so I did the best I could, i.e. vertex 2 only has one originating edge not 2.
mutual_edges <- lapply(V(gr), function(x) which_mutual(gr, es = E(gr)[from(x) | to(x)]))
df <- data.frame(Vertex=names(mutual_edges),
Edges=unlist(lapply(V(gr), function(x) length(E(gr)[from(x)]) )),
no_mutual=unlist(lapply(mutual_edges, function(x) sum(x)/2)))
df
# Vertex Edges no_mutual
#1 1 2 2
#2 2 1 1
#3 3 2 1

Remove edges by specifying endpoints

How can I delete edges from a graph by naming their endpoints?
delete_edges expects edge numbers, and it's not clear to me the mapping between endpoints and edge numbers.
library(igraph)
g = make_ring(10)
Say I wanted to remove the vertices between nodes 7&8 and nodes 9&10.
A hackish way to do so is:
g = delete_edges(g, c(7, 9))
But I had to inspect the output of E(g) closely before figuring out that those edges are numbered 7 & 9.
I tried looking for how the print methods assign the node mapping to E(g) but it looks like quite the rabbit hole.
It looks like you can do this with a string argument -- see the second example in ?delete_edges.
g = delete_edges(g, c("7|8", "9|10"))
g
# IGRAPH U--- 10 8 -- Ring graph
# + attr: name (g/c), mutual (g/l), circular (g/l)
# + edges:
# [1] 1-- 2 2-- 3 3-- 4 4-- 5 5-- 6 6-- 7 8-- 9 1--10
Apparently c("7|8", "9|10") also counts as an "edge sequence" as described in the edges argument.
Nota that:
get.edge.ids(g, c(7,8, 9, 10))
will return edge ids 7, 9. Therefore
delete_edges(g, get.edge.ids(g, c(7,8, 9, 10)))
produces the desired result:
1] 1-- 2 2-- 3 3-- 4 4-- 5 5-- 6 6-- 7 8-- 9 1--10

R: Calculating adjacent vertex after deletion of nodes

I'm very new to R and trying to calculate the adjacent vertices of a graph, which is obtained from deleting certain nodes from an original graph.
However, the output of the result doesn't match with the plot of the graph.
For example:
library(igraph)
g <- make_ring(8)
g <- add_edges(g, c(1,2, 2,7, 3,6, 4,5, 8,2, 6,2))
V(g)$label <- 1:8
plot(g)
h <- delete.vertices(g, c(1,2))
plot(h)
If I compute:
adjacent_vertices(h,6)= 5
However, I want the output to be 3,5,7 as the plot shows. The problem lies in the fact that it doesn't know I'm trying to find the adjacent vertices of node labelled 6.
Could someone please help. Thanks.
The issue here is that when you delete the vertices, the indices for the remaining vertices are shifted down to [0,6]:
> V(h)
+ 6/6 vertices:
[1] 1 2 3 4 5 6
To find the neighbors, using the original vertex names, you could then simply offset the values by the number of vertices removed, e.g.:
> neighbors(h, 6 - offset) + offset
+ 3/6 vertices:
[1] 3 5 7
A better approach, however, would be to refer to the vertex labels instead of using the indices:
> V(g)$label
[1] 1 2 3 4 5 6 7 8
> V(h)$label
[1] 3 4 5 6 7 8
> V(h)[V(h)$label == 6]
+ 1/6 vertex:
[1] 4
To get the neighbors of your vertex of interest, you can modify your code to look like:
> vertex_of_interest <- V(h)[V(h)$label == 6]
> neighbors(h, vertex_of_interest)$label
[1] 3 5 7

Resources