Inconsistency when plotting communities grouping - r

I have a problem while plotting the communities. Please consider the following MWE
library(igraph)
m <- matrix(c(0,0,0,0,0,0,
1,0,0,0,0,0,
0,0,0,0,1,0,
4,1,0,0,0,0,
0,0,0,0,0,1,
0,0,0,0,0,0),nrow=6,ncol=6)
g <- graph.adjacency(m)
memb <- membership(edge.betweenness.community(g))
memb
# [1] 1 1 2 1 2 2
I then expect to see two communities in the plot when doing
plot(g, mark.groups=list(memb), edge.width=0.5, edge.arrow.width=0.2)
But actually I get only one community
Am I doing something wrong?

You can plot the result of the community structure detection, the communities object, instead of plotting the graph. See the example in ?plot.communities.
ebc <- edge.betweenness.community(g)
plot(ebc, g)

If I understand your question correctly, then you are using the mark.groups argument wrong. Try
plot(g,
mark.groups=lapply(unique(memb), function(n) which(memb==n)),
edge.width=0.5,
edge.arrow.width=0.2)

Related

How to randomly select 2 vertices from a graph in R?

I'm new to R, and I'm trying to randomly select 2 vertices from a graph.
What I've done so far is:
First, set up a graph
edgePath <- "./project1/data/smalledges.csv"
edgesMatrix <- as.matrix(read.csv(edgePath, header = TRUE, colClasses = "character"))
graph <- graph.edgelist(edgesMatrix)
The smalledges.csv is a file look like this:
from to
4327231 2587908
Then I get all the vertices from the graph into a list:
vList <- as.list(get.data.frame(graph, what = c("vertices")))
After that, I try to use:
sample(vList, 2)
But what I've got is an error:
cannot take a sample larger than the population when 'replace = FALSE'
I guess it's because R thinks what I want is 2 random lists, so I tried this:
sample(vList, 2, replace = TRUE)
And then I've got 2 large lists... BUT THAT'S NOT WHAT I WANTED! So guys, how can I randomly select 2 vertices from my graph? Thanks!
Not clear from your question whether you want just the vertices, or a sub-graph containing those vertices. Here's an example of both.
library(igraph)
set.seed(1) # for reproducible example
g <- erdos.renyi.game(10, 0.3)
par(mfrow=c(1,3), mar=c(1,1,1,1))
set.seed(1) # for reproducible plot
plot(g)
# random sample of vertices
smpl <- sample(1:vcount(g),5)
V(g)[smpl] # 5 random vertices
# Vertex sequence:
# [1] 9 5 7 2 4
# change the color of only those vertices
V(g)[smpl]$color="lightgreen" # make them light green
set.seed(1) # for reproducible plot
plot(g)
# create a sub-graph with only those vertices, retaining edge structure
sub.g <- induced.subgraph(g,V(g)[smpl])
plot(sub.g)

Using pie charts as vertices in graph plots and specify a color for each factor

suppose i have a variable x which gives the sizes of the pie slices as follows:
x
[[1]]
Celebrity Corporate
2 6
[[2]]
Celebrity Government Unverified
2 1 4
[[3]]
Celebrity Media Unverified
5 1 6
My code was here:
plot(my_graph, vertex.shape="pie", vertex.pie=x, vertex.pie.color=???, vertex.label=NA, edge.arrow.mode=0)
My question is how could I specify colors for Celebrity, Media, Corporate, Government, and Unverified manually and plot my_graph using pie charts as vertices.
Having made said comment above, you can set the individual colors for each vertex with V().
Riffing off the pie igraph example itself:
library(igraph)
g <- graph.ring(10)
values <- lapply(1:10, function(x) c(sample(1:10,3),0,0))
# make some unique bits
values[[7]][5] = 6
values[[9]][4] = 3
# default for all
V(g)$pie.color=list(heat.colors(5))
# make one stand out
V(g)[6]$pie.color=list(topo.colors(5))
# set.seed() keeps the vertices in the same place each plot
set.seed(1492)
plot(g,
vertex.shape="pie",
vertex.pie=values,
vertex.size=seq(10, 30, length=10),
vertex.label=NA)
It should be straightforward to adapt your needs with that sample.

arranging matrix - network graphs

I was trying to make a network graph, using the function gplot from library(sna). The graph would represent the links between different fields.
I have the following data:
MTM <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1)
FI <- c(0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
MCLI <- c(0,0,1,0,0,1,1,1,0,0,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1)
mat1 <- data.frame(MTM,FI,MCLI)
mat1 <- as.matrix(mat1)
Where "MTM", "FI" and "MCLI" are the "fields of interest" and every row is a different project that has some/any/none of the fields in common.
How could I transform these data to look like this?
matx:
MTM FI MCLI
MTM 10 0 1
FI 0 1 1
MCLI 10 1 17
I am interested in representing -in a network graph- the fields as "nodes", and the connections as "edges". This could be helpful in representing the most "popular" and interconnected fields. Is it possible with these data?
Thanks in advance!
EDIT: I came across this solution, which could be OK for what I want:
library(igraph)
G<-graph.incidence(as.matrix(mat1),weighted=TRUE,directed=FALSE)
summary(G)
plot(G)
Here is one way to make a network graph from your data where each node is a "field of interest". Note that I have made a symmetrical adjacency matrix from your original data that doesn't entirely match your desired matrix output.
library(igraph)
# Use matrix multiplication to create symmetrical adjacency matrix.
adj_mat = t(mat1) %*% (mat1)
# Two ways to show edge weights.
png("igraphs.png", width=10, height=5, units="in", res=200)
par(mfrow=c(1, 2))
g1 = graph.adjacency(adj_mat, mode="undirected", diag=FALSE, weighted=TRUE)
plot(g1, edge.width=E(g1)$weight, vertex.size=50)
g2 = graph.adjacency(adj_mat, mode="undirected", diag=FALSE)
plot(g2, vertex.size=50)
dev.off()

generating a community graph in igraph

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)

2nd Degree Connections in igraph

I think have this working correctly, but I am looking to mimic something similar to Facebook's Friend suggestion. Simply, I am looking to find 2nd degree connections (friends of your friends that you do not have a connection with). I do want to keep this as a directed graph and identify the 2nd degree outward connections (the people your friends connect to).
I believe my dummy code is achieving this, but since the reference is on indices and not vertex labels, I was hoping you could help me modify the code to return useable names.
### create some fake data
library(igraph)
from <- sample(LETTERS, 50, replace=T)
to <- sample(LETTERS, 50, replace=T)
rel <- data.frame(from, to)
head(rel)
### lets plot the data
g <- graph.data.frame(rel)
summary(g)
plot(g, vertex.label=LETTERS, edge.arrow.size=.1)
## find the 2nd degree connections
d1 <- unlist(neighborhood(g, 1, nodes="F", mode="out"))
d2 <- unlist(neighborhood(g, 2, nodes="F", mode="out"))
d1;d2;
setdiff(d2,d1)
Returns
> setdiff(d2,d1)
[1] 13
Any help you can provide will be great. Obviously I am looking to stay within R.
You can index back into the graph vertices like:
> V(g)[setdiff(d2,d1)]
Vertex sequence:
[1] "B" "W" "G"
Also check out ?V for ways to get at this type of info through direct indexing.
You can use the adjacency matrix $G$ of the graph $g$ (no latex here?). One of the properties of the adjacency matrix is that its nth power gives you the number of $n$-walks (paths of length n).
G <- get.adjacency(g)
G2 <- G %*% G # G2 contains 2-walks
diag(G2) <- 0 # take out loops
G2[G2!=0] <- 1 # normalize G2, not interested in multiplicity of walks
g2 <- graph.adjacency(G2)
An edge in graph g2 represents a "friend-of-a-friend" bond.

Resources