Subset graph based on edges weight - r

I have a graph, G=(V,E) with several attributes including an edge weight attribute. I'm trying to create a subgraph based on a condition where weights are higher than x.
I've tried the standard R subsetting option with g <- E(g)[weight > max(weight)*.10], but I always get a vector.
I'm not sure what I'm doing wrong here.

Maybe you want something like this
library(igraph)
set.seed(1)
m <- matrix(sample(c(.5, 2, 5), 100, replace=T, prob = c(.6,.3,.1)), nc=10, dimnames = rep(list(letters[1:10]), 2))
g <- graph_from_adjacency_matrix(m, weighted=T, diag=F, mode="undirected")
coords <- layout.auto(g)
par(mfrow = c(1,3))
plot(g, layout=coords, edge.width = E(g)$weight)
s1 <- subgraph.edges(g, E(g)[E(g)$weight>2], del=F)
plot(s1, layout=coords, edge.width = E(s1)$weight)
s2 <- delete_vertices(s1, degree(s1, mode = "in")==0)
plot(s2, layout=coords[V(g)$name%in%V(s2)$name,], edge.width = E(s2)$weight)

That would be because you replaced your graph g with just subsetted edges. If you want to remove edges below the threshold weight, you can use:
g_sub <- delete.edges(g, E(g)[weight <= max(weight)*.10])

Related

Bipartite graph projection with nodes as edge attributes

I have a bipartite graph and I want the projections of this graph to have edge attributes that record via which nodes they were connected. For example:
require(igraph)
set.seed(123)
g <- sample_bipartite(5, 5, p =.5)
V(g)$name <- c(letters[1:5], 1:5)
g1 <- bipartite_projection(g)[[1]]
g2 <- bipartite_projection(g)[[2]]
par(mfrow = c(1, 3))
plot(g,
vertex.shape = ifelse(V(g)$type == FALSE, "square", "circle"),
vertex.color = ifelse(V(g)$type == FALSE, "gold", "tomato"),
main = "Bipartite")
plot(g1,
main = "Projection 1")
plot(g2,
main = "Projection 2")
par(mfrow = c(1, 1))
I want the information that I added by hand to the plot to be in the network object. It it easily done in igraph? Thanks.
With bipartite_projection
If you really want ot use bipartite_projection, you can try to define your custom function f like below:
f <- function(gp) {
df <- get.data.frame(gp)[1:2]
df$lbl <- apply(
df,
1,
function(v) {
max(do.call(intersect, unname(lapply(v, function(x) names(neighbors(g, x))))))
}
)
res <- graph_from_data_frame(df, directed = FALSE)
plot(res, edge.label = E(res)$lbl)
}
f(g1)
f(g2)
which gives
Without bipartite_projection
Below is an option without using bipartite_projection (take g1 as the an example, and g2 can be obtained in a similar way)
g1 <- simplify(
graph_from_data_frame(
do.call(
rbind,
lapply(
Filter(
function(x) nrow(x) > 1,
split(get.data.frame(g), ~to)
),
function(d) {
with(
d,
cbind(data.frame(t(combn(from, 2))), weight = unique(to))
)
}
)
),
directed = FALSE
),
edge.attr.comb = "max"
)
and plot(g1, edge.label = E(g1)$weight) gives
First, I made a dataframe of the as.edgelist results, then computed a label with paste0. Next, I used the edge_attr command to write the labels to the graph object.
el<-igraph::as_edgelist(g);el<-as.data.frame(el)
el$lab<-paste0(el$V1,"_",el$V2)
edge_attr(g,"label")<-el$lab
E(g)$label
set.seed(232)
plot(g,
edge.label.dist=.3,
edge.label.color="blue",
margin=-0.4,
layout=layout.fruchterman.reingold)

How to create a graph from an adjacency matrix by also specifying nodes coordinates in igraph?

I have the following R code:
library('igraph')
nodes <- c('a','b','c','d')
x <- c(0,1,2,3)
y <- c(0,1,2,3)
from <- c('a','b','c')
to <- c('b','c','d')
NodeList <- data.frame(nodes, x ,y)
EdgeList <- data.frame(from, to)
plot(graph_from_data_frame(vertices = NodeList, d= EdgeList, directed = FALSE))
Which emits the graph I want. However I need to be able to use the adjacency matrix instead of from and to vectors. Function graph_from_adjacency_matrix does not include a parameter to specify the coordinates of nodes. How to achieve this?
[As #user20650 mentioned above], you can specify the coordinates of the vertices latter, using vertex_attr():
library('igraph')
adjm <- matrix(
c(0, rep(c(1, 0, 0, 0, 0), times = 3)), 4, , F, list(letters[1:4], letters[1:4])
)
g01 <- graph_from_adjacency_matrix(adjm, 'undirected') -> g02
vertex_attr(g02, name = 'x') <- c(0, 0, 1, 1)
vertex_attr(g02, name = 'y') <- c(0, 1, 1, 0)
par(mfrow = 1:2)
plot(g01)
plot(g02)

R igraph: label vertex by condition

I have a graph g with a set of vertices and a list with the names of some "special" vertices.
I want the graph to display a label with the vertex name ONLY for these special vertices.
I tried something like this:
plot(g, vertex.size = 4, vertex.label = ifelse(V(g) %in% usernames, V(g)$label, ""), asp = F)
But apparently I'm missing something, because the predicate never enter TRUE.
Also, it seems like V(g)$label results in the following error:
Error in ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok] : replacement has length zero
Your help will be appreciated! :)
Turn V(g) into V(g)$label?
set.seed(1)
library(igraph)
g <- ba.game(26)
V(g)$label <- letters[1:26]
usernames <- sample(letters, 5)
plot(g, vertex.label = ifelse(V(g)$label %in% usernames, V(g)$label, NA))
or
set.seed(1)
library(igraph)
g <- ba.game(26)
usernames <- sample(vcount(g), 5)
plot(g, vertex.label = ifelse(V(g) %in% usernames, V(g), NA))
?

igraph use of %>% as continuation

I am using igraph with R
trying to create a graph with labeled vertices.
THe igraph docs for "paths" give the example code
g <- make_empty_graph(directed = FALSE, n = 10) %>%
set_vertex_attr("name", value = letters[1:10])
plot(g) # labels the vertices with letters a through j
However
g <- make_empty_graph(directed = FALSE, n = 10)
set_vertex_attr(g, "name", value = letters[1:10])
plot(g) # now labels the vertices as numbers 1:10
Why?
The igraph docs for "set_vertex_attributs" use
set_vertex_attr(g, "name", value = letters[1:10])
to set vertex attributes.

normalized local closeness centrality in R igraph::estimate_closeness()

I am trying to calculate a normalized local closeness centrality. But setting the parameter normalized = T for igraph::estimate_closeness() only multiplies the results with (N-1). Is it possible to define N_i for vertex i individually by it's neighborhood, that is determined by the cut-off parameter (and of course by the graph itself)?
The mini example demonstrates, that setting the parameter normalized=T does not work for this purpose. It normalizes with one and the same (N-1) for all vertices.
Thanks for help.
set.seed(1210)
require('igraph')
g <- random.graph.game(20,3/10)
g <- set.edge.attribute(g, "weight", value= 1)
cnt <- estimate_closeness(g, cutoff = 3, normalized = T );cnt
cnf <- estimate_closeness(g, cutoff = 3, normalized = F );cnf
#print results
cbind(cnf * (length(V(g))-1), cnt)
sum(abs(cnf * (length(V(g))-1) - cnt))
#for visualization
V(g)$name <- paste("v", 1:length(V(g)), sep="")#letters[1:length(V(g))]
set.seed(2)
lay <- layout.auto(g)
## set plotting parameters
vs <- 15# vertex.size
ec <- gray(0.8)#edge.color
elx <- 2# edge.label.cex
elc <- "black"#,edge.label.color
vlc <- 2#vertex.label.cex
ew <- 2#edge.width
hd <- paste(rep(" ",0), collapse="")
cm <- 3
vc <- "orange"#gray(0.8)#palette("default")#"grey"#vertex.color
windows(width = 18, height=6)
par(mfrow=c(1,3))
plot(g, edge.label=paste(hd, round(E(g)$weight,1)), layout=lay, vertex.size=vs, edge.color=ec, edge.label.cex=elx, vertex.label.cex=vlc, edge.width=ew, edge.label.color=elc, vertex.color=vc)
title("(a) Weights", cex.main = cm)
V(g)$name <- paste(round(cnt,3))
plot(g, layout=lay, vertex.size=vs, edge.color=ec, edge.label.cex=elx, vertex.label.cex=vlc, edge.width=ew, edge.label.color=elc, vertex.color=vc)
title("(b) local closeness normalized", cex.main = cm)
V(g)$name <- paste(round(cnf,3))
plot(g, layout=lay, vertex.size=vs, edge.color=ec, edge.label.cex=elx, vertex.label.cex=vlc, edge.width=ew, edge.label.color=elc, vertex.color=vc)
title("(c) local closeness", cex.main = cm)

Resources