R igraph: Replacing node names, adding attributes - r

I have following sample for a graph in R igraph:
# Erdos
g <- erdos.renyi.game(100, 1/100)
V(g)$size<-seq(0.05,1,0.05)
# Draw nodes and save positions
locs <- layout.fruchterman.reingold(g)
plot(g, layout=locs, vertex.label=NA, main="Original")
# Show igraph data
g
Generally, I like to know how
The current node names can be replaced with new ones and
How this can be combined with adding new node information.
This is how the dataframe with the new information looks like:
node_old node_new Type More_Data
1 5 1 AA 122.5
2 2 2 BB 80.4
3 12 3 CC 104.3
"Type" and "More_Data" are the information that I like to assign to the nodes.
Thanks!

if '5' is node name, then
V(g)$label[V(g)$label=='5'] <- '1'
V(g)$Type[V(g)$label=='5'] <- 'AA'
V(g)$More_Data[V(g)$label=='5'] <- 122.5
if '5' is 5th node,
V(g)$Type[5] <- 'AA'
V(g)$More_Data[5] <- 122.5

Related

how to convert a node list to an edge list in igraph?

I have a empty graph and need to plot the graph based on the convex hull with inner verticies.
My attemp is:
library(igraph)
set.seed(45)
n = 10
g <- graph.empty(n)
xy <- cbind(runif(n), runif(n))
vp <- convex_hull(xy)$resverts + 1
#[1] 8 10 7 2 1
## convert node_list to edge_list
plot(g, layout=xy)
Expected result in right figure.
Question. How to convert a node list to an edge list in igraph??
You can use add_edges along with embed
g2 <- g %>%
add_edges(c(t(embed(vp, 2)), vp[1], vp[length(vp)])) %>%
as.undirected()
and plot(g2, layout = xy) in turn gives
convex_hull does not output a node list in the same sense that an igraph object has a node list. In this case, vp is the sequence of indices so in order to create an edge list, you just need to have the from vertex be going to the next vertex in the sequence. This can be accomplished with dplyr::lead using the first vertex as the default to create a circuit.
data.frame(
from = vp,
to = dplyr::lead(vp, 1, default = vp[1])
)
#> from to
#> 1 8 10
#> 2 10 7
#> 3 7 2
#> 4 2 1
#> 5 1 8
Try this.
## create graph.
vids <- as.character(c(8, 10, 7, 2, 1))
g <- make_graph(c(), length(vids))
V(g)$name <- vids
## and connect the dots.
g2 <- g + path(c(vids, vids[1]))
g2

Contract verticies by attribute with igraph

I am working on a graph, where each node has an attribute "group" of the following: "Baby Product", "Book" "CE" "DVD" "Music" "Software" "Toy" "Video" "Video Games".
I would like to know how to plot a graph reppresenting those communities: there shall be 9 verticies, one for each group, and a link (possibly weighted) each time two nodes of two categories are connected.
I have tried using the igraph contract function, but this is the result:
> contract(fullnet, mapping=as.factor(products$group), vertex.attr.comb = products$group)
Error in FUN(X[[i]], ...) :
Unknown/unambigous attribute combination specification
Inoltre: Warning message:
In igraph.i.attribute.combination(vertex.attr.comb) :
Some attributes are duplicated
I guess I have misunderstood what this function is used for.
Now I am thinking about creating a new edgelist, made like the one before but instead of the Id of each vertex the name of the group. Sadly, I do not know how to do this in a fast way on an edgelist of over 1200000 elements.
Thank you very much in advance.
I think using contract() should be correct. In the example code below, I added an anonymous function to vertex.attr.comb to combine the vertices by group. Then, simplify() removes loop edges and calculate the sum of edge weight.
# Create example graph
set.seed(1)
g <- random.graph.game(10, 0.2)
V(g)$group <- rep(letters[1:3], times = c(3, 3, 4))
E(g)$weight <- 1:length(E(g))
E(g)
# + 9/9 edges from 7017c6a:
# [1] 2-- 3 3-- 4 4-- 7 5-- 7 5-- 8 7-- 8 3-- 9 2--10 9--10
E(g)$weight
# [1] 1 2 3 4 5 6 7 8 9
# Contract graph by `group` attribute of vertices
g1 <- contract(g, factor(V(g)$group),
vertex.attr.comb = function(x) levels(factor(x)))
# Remove loop edges and compute the sum of edge weight by group
g1 <- simplify(g1, edge.attr.comb = "sum")
E(g1)
# + 3/3 edges from a852397:
# [1] 1--2 1--3 2--3
E(g1)$weight
# [1] 2 15 12

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)

How can I export the link dataframe from a network graph in igraph?

I have a randomly generated graph like the following:
g <- erdos.renyi.game(30, 151 , type = "gnm" , directed = F , loops = F)%>%
set_vertex_attr("a", value = 0)
Is there a way that I can retrieve a link dataframe that looks like this:
id id2
1 2
1 3
2 4
3 5
4 5
What you are looking for seems to be what igraph calls the "edge list". You can get that with
as_edgelist(g)
or if you want to include vertex attributes,
as_long_data_frame(g)

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

Resources