I have 2 graphs, lets call them g1 and g2. The graph g2 has the same structure as g1 but contains new edges that are not present in g1. I have to find these edges.
g1 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5), n=5, directed=FALSE)
g2 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5,3,5), n=5, directed=FALSE)
In this case what i'm looking for is the edge 3--5.
So far i thought of using the complementer of g1 then matching it with the edges from g2 to find these new edges. The problem is that i'm having trouble with the syntax. (new to R)
g1_complement <- complementer(g1)
Now i'd like to get only the new edges that are in g2 but NOT in g1. I was thinking of doing this.
E(g1_complement)[E(g1_complement) %in% E(g2)]
I was expecting to get only the new edges, but this returns all the g1_complement edges. I am only using igraph as library.
Please find below one possible solution using the difference() function from the igraph library.
Reprex
library(igraph)
g1 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5), n=5, directed=FALSE)
g2 <- graph(edges=c(1,2,2,3,1,3,3,4,2,4,1,5,3,5), n=5, directed=FALSE)
difference(g2, g1)
#> IGRAPH 9fb5e8c U--- 5 1 --
#> + edge from 9fb5e8c:
#> [1] 3--5
Created on 2022-01-30 by the reprex package (v2.0.1)
We can try
> E(g2)[!E(g2) %in% E(g1)]
+ 1/7 edge from 9fdc2d2:
[1] 3--5
> E(g2)[setdiff(E(g2), E(g1))]
+ 1/7 edge from 9fdc2d2:
[1] 3--5
Related
In Python you can simply use graph.select() (atleast when reading the documentation: https://igraph.org/python/doc/api/igraph.VertexSeq.html) to select a vertex based on a value. I have a huge graph connecting movies that share an actor. However I would simply like to select one vertex from that graph and then plot it with its direct neighbors. I'm running into issues when I want to select just that single vertex.
I had hoped something like worked
graph.movies.select('Snatch (2000)')
But no luck.
Another approach I took was grabbing the single Snatch vertex by filtering all others out and then adding the edges.
snatch.graph <- induced.subgraph(g.movies, vids=V(g.movies)$name == 'Snatch (2000)')
snatch.edges <- edges(g.movies, "Snatch (2000)")
add_edges(snatch.graph, snatch.edges$edges)
However this returns an empty graph with only the snatch vertex.
My goal is to grab the Snatch vertex and plot this vertex, its DIRECT neighbors and the edges amomng them. Any suggestions? Thanks alot :D Been stuck o nthis for a quite a while -.-
You can use ?ego to grab the neighbours or ?make_ego_graph to form the graph. (Depending on whether your graph is directed or not, you may need to use the mode argument).
An example:
library(igraph)
# create some data
set.seed(71085002)
n = 10
g = random.graph.game(n, 0.25)
V(g)$name = seq_len(n)
# grab neighbours of node "1"
# set mindist = 0 to include node itself
# set order for the stepsize of the neigbourhood;
nb_g = make_ego_graph(g, order=1, node="1", mindist=0)[[1]]
# plot
# you could use the `layout` argument to
# keep nodes in the same position
op = par(mfrow=c(1,2), oma=rep(0,4))
plot(g, vertex.size=0, vertex.label.cex=3, main="Full graph")
plot(nb_g, vertex.size=0, vertex.label.cex=3, main="Sub graph")
par(op) # reset
If you just need a list of the neighbouring nodes:
ego(g, order=1, node="1", mindist=0)
# [[1]]
# + 4/10 vertices, named, from 00cfa70:
# [1] 1 4 6 9
I think the method using ego (by #user20650) is comprehensive and efficient.
Here is another option if you would like to find the sub-graph built on direct neighbors, which applies distances + induced_subgraph
> induced_subgraph(g, which(distances(g, "1") <= 1))
IGRAPH 99f872b UN-- 4 3 -- Erdos renyi (gnp) graph
+ attr: name (g/c), type (g/c), loops (g/l), p (g/n), name (v/n)
+ edges from 99f872b (vertex names):
[1] 1--4 1--6 1--9
I'm pretty new to R. I wanna know that given a list of node ID's of a graph is there any fast way to connect all the edges between that vertices and create a clique in that graph?
p.s: I'm looking for a really fast method because I'm working on a very large graph.
Thanks in advance.
Given a vector of vertices idx, we may use combn to create a vector of edges to be added:
g1 <- erdos.renyi.game(20, 1 / 20)
idx <- 3:8
g2 <- g1 + edges(c(combn(idx, 2)))
maximal.cliques(g2)
# ...
# [[14]]
# + 6/20 vertices, from 137d7ad:
# [1] 6 3 8 7 5 4
I identify the neighbors of a selected node but haven’t been able to plot the result. Take the following example, copied from another question:
edgelist <- read.table(text = "
A B
B C
C D
D E
C F
F G")
library(igraph)
graph <- graph.data.frame(edgelist)
str(graph)
#IGRAPH DN-- 7 6 --
# + attr: name (v/c)
# + edges (vertex names):
# [1] A->B B->C C->D D->E C->F F->G
I identify the neighbors of "D" with:
neighborsD <- neighbors(graph, "D")
But when I instruct R to plot "neighborsD"...
plot(neighborsD)
... I get a chart instead of a sociogram, and when I try to tkplot it I get the error "not a graph object". So two questions:
1) How do I plot the network around, say, "D"?
2) How do I plot “D”, its neighbors, and the neighbors of the neighbors (two steps from "D"?
Use the ego() function to find nodes that are a certain distance away from a a node. And then use induced_subgraph to subset your main graph. For example, the does that are 1 step away are
plot(induced_subgraph(graph, ego(graph, 1, "D")[[1]]))
and those that are two steps away are
plot(induced_subgraph(graph, ego(graph, 2, "D")[[1]]))
Using R and igraph, I have two graphs I have combined, then run constraint() on. Constraint works on g1 but when I add g2, constraint() returns NA for the new vertices added from g2 and vertices next to these new vertices.
Here is example code that replicates my problem. I obtain g1 from a projection of a bipartite graph, as this reflects my data process.
My problem may be an issue with the union of the two graphs, but either way I try it (g3 <- g1 + g2 or g3 <- graph.union(g1, g2)) the constraint calculation is bringing NAs.
set.seed(42)
g <- sample_bipartite(100, 10, type = c("gnp"), p=.03, directed = FALSE)
gproj <- bipartite_projection(g, types=NULL, multiplicity = TRUE)
g1 <- gproj[[1]]
V(g1)$name <- 1:vcount(g1) #this gets their actual vertex id to show as label
V(g1)$name
components <- decompose.graph(g1)
largest <- which.max(sapply(components, vcount))
largest #this tells me which component is largest
lc <- components[[largest]]
lc
plot(lc)
cg1 <- constraint(lc)
cg1 #constraint for all connected vertices is calculated
#Create g2, some vertices in g1, some are new
rel <- data.frame( rel1 =
c(95), rel2 =
c(2000), stringsAsFactors = F) #create edgelist of g2, one vertex in lc, one vertex new
g2 <- graph.data.frame(rel, directed=FALSE)
#combine graphs and calculate constraint on combined graph
#g1 is used instead of lc because relationships in g2 may connect previously isolated vertices/components
g3 <- g1 + g2
components1 <- decompose.graph(g3)
largest1 <- which.max(sapply(components1, vcount))
largest1 #this tells me the first component is largest
lc1 <- components1[[largest1]]
plot(lc1)
cg3 <- constraint(lc1)
cg3 #now constraint vertices close to 2000 is 'NA'
For further information, other igraph measures such as eigenvector centrality, degree, and bonpower do not experience this issue.
Through some additional investigation, I have figured out a solution. The issue was g1 had weights, while g2 did not. With the weights removed, using this code (and using g1a down the line) constraint calculates for all vertices.
g1a <- remove.edge.attribute(g1, "weight")
Even better than it working for this toy example, this solution worked for my full, much larger, dataset.
I have been searching for an answer to this question but could not find any mention, so I decided to post here. I am trying to see if igraph or any packages provide a simple way to create a "community graph" where each node represents a community in the network and the ties represent ties between the communities. I can get the community detection algorithm to work fine in igraph, but I could not find a way to collapse the results to just show connections between each community. Any assistance would be appreciated.
You can simply use the contract.vertices() function. This contracts groups of vertices into a single vertex, essentially the same way you want it. E.g.
library(igraph)
## create example graph
g1 <- graph.full(5)
V(g1)$name <- 1:5
g2 <- graph.full(5)
V(g2)$name <- 6:10
g3 <- graph.ring(5)
V(g3)$name <- 11:15
g <- g1 %du% g2 %du% g3 + edge('1', '6') + edge('1', '11')
## Community structure
fc <- fastgreedy.community(g)
## Create community graph, edge weights are the number of edges
cg <- contract.vertices(g, membership(fc))
E(cg)$weight <- 1
cg2 <- simplify(cg, remove.loops=FALSE)
## Plot the community graph
plot(cg2, edge.label=E(cg2)$weight, margin=.5, layout=layout.circle)