graphNEL
(node/edge list representation)
graphAM
(adjacency matrix)
igraph
object (part of the igraph package)I used the following libraries to generate these slides.
require(igraph)
require(knitr)
require(visNetwork)
require(shiny)
The igraph package has parsers for reading in most of the general file formats for networks. Let’s load in the Karate network from Network Example Data. It’s in GML format, so we’ll need to specify that when we use read_graph()
.
library(igraph)
karate <- read_graph("data/karate.gml", format="gml")
class(karate)
## [1] "igraph"
plot.igraph(karate)
That’s not very informative, especially since the original data doesn’t have labels. Let’s add some:
get.vertex.attribute(karate, "id")
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
## [24] 24 25 26 27 28 29 30 31 32 33 34
karate <- set.vertex.attribute(karate, "name",
value=c("Chloe", "Emily", "Aaliyah", "Emma",
"Jennifer", "Olivia", "Hannah",
"Jessica", "Sarah", "Lily", "Charlotte",
"Elizabeth", "Abigail", "Rebecca",
"Samantha", "Jacob", "Muhammad", "Shawn",
"Aaron", "Daniel", "Jonah", "Alex",
"Michael", "James", "Ryan", "Jordan",
"Alexander", "Ali", "Tyler", "Kevin",
"Jack", "Ethan", "Luke", "Harry"))
#V() is a way to programmatically access vertices (or nodes) for igraph
V(karate)
## + 34/34 vertices, named:
## [1] Chloe Emily Aaliyah Emma Jennifer Olivia Hannah
## [8] Jessica Sarah Lily Charlotte Elizabeth Abigail Rebecca
## [15] Samantha Jacob Muhammad Shawn Aaron Daniel Jonah
## [22] Alex Michael James Ryan Jordan Alexander Ali
## [29] Tyler Kevin Jack Ethan Luke Harry
#get the ids (as a vector)
V(karate)$name
## [1] "Chloe" "Emily" "Aaliyah" "Emma" "Jennifer"
## [6] "Olivia" "Hannah" "Jessica" "Sarah" "Lily"
## [11] "Charlotte" "Elizabeth" "Abigail" "Rebecca" "Samantha"
## [16] "Jacob" "Muhammad" "Shawn" "Aaron" "Daniel"
## [21] "Jonah" "Alex" "Michael" "James" "Ryan"
## [26] "Jordan" "Alexander" "Ali" "Tyler" "Kevin"
## [31] "Jack" "Ethan" "Luke" "Harry"
#look at edges
E(karate)
## + 78/78 edges (vertex names):
## [1] Chloe --Emily Chloe --Aaliyah Emily --Aaliyah
## [4] Chloe --Emma Emily --Emma Aaliyah --Emma
## [7] Chloe --Jennifer Chloe --Olivia Chloe --Hannah
## [10] Jennifer--Hannah Olivia --Hannah Chloe --Jessica
## [13] Emily --Jessica Aaliyah --Jessica Emma --Jessica
## [16] Chloe --Sarah Aaliyah --Sarah Aaliyah --Lily
## [19] Chloe --Charlotte Jennifer--Charlotte Olivia --Charlotte
## [22] Chloe --Elizabeth Chloe --Abigail Emma --Abigail
## [25] Chloe --Rebecca Emily --Rebecca Aaliyah --Rebecca
## [28] Emma --Rebecca Olivia --Muhammad Hannah --Muhammad
## + ... omitted several edges
#layout example from https://rulesofreason.wordpress.com/2012/11/05/network-visualization-in-r-with-the-igraph-package/
plot.igraph(karate, layout=layout.fruchterman.reingold, # the layout method. see the igraph documentation for details
main='Karate Friends!', #specifies the title
#vertex.label.dist=0.5, #puts the name labels slightly off the dots
vertex.label.color='black', #the color of the name labels
vertex.label.font=1, #the font of the name labels
vertex.label=V(karate)$name, #specifies the labels of the vertices. in this case the 'name' attribute is used
vertex.label.cex=0.75, #specifies the size of the font of the labels. can also be made to vary
vertex.size=degree(karate)*1.5, #make node size proportional to number of connections
edge.arrow.size=2
)
Each element of a graph (vertices and edges) can be customized by passing in the appropriate attribute. For more info, check out http://www.inside-r.org/packages/cran/igraph/docs/attributes.
Some properties are automatically mapped, such as V(graph)$color
or E(graph)$color
. If you add a new attribute, you’ll need to map this to a plotting property in plot.igraph()
Remember, that after changing graph properties, such as node size, you need to run your layout_
function again.
#setting node properties
#can also use set.vertex.attributes() here
newKarate <- karate
faction <- c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2,
1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
V(newKarate)$color <- faction
#Set edge attributes using E(accessor)
#can pass a named list for each node as well
#You can also use set.edge.attributes() here
E(newKarate)$color <- "red"
#Here we instantiate a weight vector using sample
weightvec <- sample(c(1,2,3,4), length(E(newKarate)), replace = TRUE)
#Name each edge
names(weightvec) <- E(newKarate)$name
weightvec
## [1] 2 3 2 3 2 4 1 3 3 1 3 4 2 2 1 3 4 3 1 1 1 3 3 2 2 2 3 3 1 1 4 3 1 1 4
## [36] 4 2 1 1 1 1 3 1 4 3 1 4 4 4 4 1 4 2 4 4 3 4 1 2 2 1 4 2 4 2 3 3 3 2 3
## [71] 2 4 3 3 3 1 2 3
E(newKarate)$weight <- weightvec
#note we need to map an attribute to a property of the graph (igraph is dumb)
plot(newKarate, edge.width=E(karate)$weight)
Degree Distribution and Average Path Length
degree(karate)
## Chloe Emily Aaliyah Emma Jennifer Olivia Hannah
## 16 9 10 6 3 4 4
## Jessica Sarah Lily Charlotte Elizabeth Abigail Rebecca
## 4 5 2 3 1 2 5
## Samantha Jacob Muhammad Shawn Aaron Daniel Jonah
## 2 2 2 2 2 3 2
## Alex Michael James Ryan Jordan Alexander Ali
## 2 2 5 3 3 2 4
## Tyler Kevin Jack Ethan Luke Harry
## 3 4 4 6 12 17
sort(degree(karate), decreasing = TRUE)
## Harry Chloe Luke Aaliyah Emily Emma Ethan
## 17 16 12 10 9 6 6
## Sarah Rebecca James Olivia Hannah Jessica Ali
## 5 5 5 4 4 4 4
## Kevin Jack Jennifer Charlotte Daniel Ryan Jordan
## 4 4 3 3 3 3 3
## Tyler Lily Abigail Samantha Jacob Muhammad Shawn
## 3 2 2 2 2 2 2
## Aaron Jonah Alex Michael Alexander Elizabeth
## 2 2 2 2 2 1
hist(degree(karate))
average.path.length(karate)
## [1] 2.4082
shortPaths <- get.shortest.paths(karate, from="Muhammad")
plot(karate, mark.groups=shortPaths$vpath[c(10)])
Let’s generate a random walk from Jennifer and see where we get.
w <- random_walk(karate, start = "Jennifer", steps =1000)
#who is the most visited?
sort(table(w$name), decreasing = TRUE)
##
## Chloe Harry Luke Aaliyah Emily Ethan Olivia
## 120 102 65 52 47 42 35
## Jordan Rebecca Emma Hannah James Charlotte Jessica
## 33 33 31 31 31 28 28
## Sarah Jennifer Ryan Ali Daniel Jack Jacob
## 28 25 25 23 23 21 21
## Tyler Kevin Jonah Abigail Muhammad Aaron Lily
## 19 17 15 14 14 13 12
## Alex Elizabeth Michael Samantha Alexander Shawn
## 11 11 10 8 6 6
#normalize table by number of visits
probKarate <- table(w$name)/1000
Who are the influencers (or hubs) in this social network? Let’s use some network centrality measures to see. Are there any differences?
Who gives the highest correlation with our drunken walk probabilities?
pr <- page.rank(karate)
sort(pr$vector, decreasing = TRUE)
## Harry Chloe Luke Aaliyah Emily Ethan
## 0.100919182 0.096997285 0.071693226 0.057078509 0.052876924 0.037158087
## Emma James Sarah Rebecca Olivia Hannah
## 0.035859858 0.031522515 0.029766056 0.029536456 0.029111155 0.029111155
## Kevin Ali Jack Jessica Jennifer Charlotte
## 0.026288538 0.025639767 0.024590155 0.024490497 0.021977952 0.021977952
## Ryan Jordan Daniel Tyler Muhammad Alexander
## 0.021076034 0.021006197 0.019604636 0.019573459 0.016784005 0.015044038
## Abigail Shawn Alex Samantha Jacob Aaron
## 0.014644892 0.014558677 0.014558677 0.014535994 0.014535994 0.014535994
## Jonah Michael Lily Elizabeth
## 0.014535994 0.014535994 0.014309397 0.009564745
nk <- V(karate)$name
cor(pr$vector[nk], probKarate[nk])
## [1] 0.9684656
ec <- eigen_centrality(karate)
sort(ec$vector, decreasing = TRUE)
## Harry Chloe Aaliyah Luke Emily Sarah
## 1.00000000 0.95213237 0.84955420 0.82665886 0.71233514 0.60906844
## Rebecca Emma Ethan Jack Jessica James
## 0.60657439 0.56561431 0.51165649 0.46806481 0.45789093 0.40207086
## Daniel Kevin Ali Tyler Lily Jacob
## 0.39616224 0.36147301 0.35749923 0.35107297 0.27499812 0.27159396
## Samantha Jonah Aaron Michael Shawn Alex
## 0.27159396 0.27159396 0.27159396 0.27159396 0.24747879 0.24747879
## Abigail Hannah Olivia Charlotte Jennifer Alexander
## 0.22566382 0.21288383 0.21288383 0.20347148 0.20347148 0.20242852
## Jordan Ryan Elizabeth Muhammad
## 0.15857597 0.15280670 0.14156633 0.06330461
cor(ec$vector[nk], probKarate[nk])
## [1] 0.8240622
hs <- hub_score(karate)
sort(hs$vector, decreasing = TRUE)
## Harry Chloe Aaliyah Luke Emily Sarah
## 1.00000000 0.95213237 0.84955420 0.82665886 0.71233514 0.60906844
## Rebecca Emma Ethan Jack Jessica James
## 0.60657439 0.56561431 0.51165649 0.46806481 0.45789093 0.40207086
## Daniel Kevin Ali Tyler Lily Samantha
## 0.39616224 0.36147301 0.35749923 0.35107297 0.27499812 0.27159396
## Jacob Aaron Jonah Michael Shawn Alex
## 0.27159396 0.27159396 0.27159396 0.27159396 0.24747879 0.24747879
## Abigail Olivia Hannah Jennifer Charlotte Alexander
## 0.22566382 0.21288383 0.21288383 0.20347148 0.20347148 0.20242852
## Jordan Ryan Elizabeth Muhammad
## 0.15857597 0.15280670 0.14156633 0.06330461
cor(hs$vector[nk], probKarate[nk])
## [1] 0.8240622
Who’s the most connected groups to each other? Enquiring minds want to know…
##get all cliques in the data
karateCliques <- cliques(karate)
length(karateCliques)
## [1] 170
#let's try finding the largest cliques
largeKarateCliques <- largest_cliques(karate)
largeKarateCliques
## [[1]]
## + 5/34 vertices, named:
## [1] Jessica Chloe Emily Aaliyah Emma
##
## [[2]]
## + 5/34 vertices, named:
## [1] Emma Chloe Emily Aaliyah Rebecca
Can we split the network up into smaller communities? There are number of community detection algorithms we can use to see if we can cleanly separate our network into smaller modules, or communities.
##Segment the karate network using the fast-greedy algorithm
fgComm <- fastgreedy.community(karate)
plot(fgComm, karate)
##Segment the karate network using the walktrap algorithm
wkComm <- walktrap.community(karate)
plot(wkComm, karate)
##how close are the algorithms?
compare(membership(fgComm), membership(wkComm))
## [1] 1.14204
If there is a community of interest, we can use induced.subgraph
.
##extract the membership vector for the fastgreedy community
fgCommMembers <- membership(fgComm)
##let's extract the one of the cliques
clique1 <- induced.subgraph(karate, v=largeKarateCliques[[1]]$name)
plot(clique1)
#how many different communities are there?
levels(factor(fgCommMembers))
## [1] "1" "2" "3"
comm1 <- induced.subgraph(karate, fgCommMembers == 1)
plot(comm1)
How do we find all of Emma’s friends?
emmasNeighbors <- neighbors(karate, v="Emma", mode="all")
emmaSubnet <- c("Emma",emmasNeighbors$name)
emmaSubnet
## [1] "Emma" "Chloe" "Emily" "Aaliyah" "Jessica" "Abigail" "Rebecca"
emmaSubgraph <- induced.subgraph(karate, emmaSubnet)
plot(emmaSubgraph)
igraph’s built in plotting is not super customizable, but you can change layouts. All of the different igraph layouts begin with “layout_”.
#circle plot
plot(karate, layout=layout_in_circle)
#layout plot on grid
plot(karate, layout=layout_on_grid)
#force-directed layout for large graphs
plot(karate, layout=layout_with_lgl)
#layout plot with center (star layout)
plot(karate, layout=layout_as_star)
#layout plot on grid
plot(karate, layout=layout_with_dh)
Oftentimes, you will need to generate a bunch of graphs from scratch, for a background distribution. There are some built in functions to do that.
#Random Graphs
rgGraph <- random.graph.game(34, p.or.m = 0.2)
plot(rgGraph)
hist(degree(rgGraph))
#Erdos Renyi Graphs
erGraph <- erdos.renyi.game(34, 0.1)
plot(erGraph)
hist(degree(erGraph))
#Barabasi graphs - power law distributed
bgGraph <- barabasi.game(34, 1)
plot(bgGraph)
#Confirm edge distribution is correct
hist(degree(bgGraph))
The graph package (not the igraph package!) contains the graphNEL and graphAM representations. I don’t really go into using them here, but just know that you can convert back and forth from these different representations using different commands.
library(graph)
## Loading required package: BiocGenerics
## Loading required package: parallel
##
## Attaching package: 'BiocGenerics'
## The following objects are masked from 'package:parallel':
##
## clusterApply, clusterApplyLB, clusterCall, clusterEvalQ,
## clusterExport, clusterMap, parApply, parCapply, parLapply,
## parLapplyLB, parRapply, parSapply, parSapplyLB
## The following objects are masked from 'package:igraph':
##
## normalize, union
## The following object is masked from 'package:gridExtra':
##
## combine
## The following objects are masked from 'package:stats':
##
## IQR, mad, xtabs
## The following objects are masked from 'package:base':
##
## anyDuplicated, append, as.data.frame, cbind, colnames,
## do.call, duplicated, eval, evalq, Filter, Find, get, grep,
## grepl, intersect, is.unsorted, lapply, lengths, Map, mapply,
## match, mget, order, paste, pmax, pmax.int, pmin, pmin.int,
## Position, rank, rbind, Reduce, rownames, sapply, setdiff,
## sort, table, tapply, union, unique, unsplit, which, which.max,
## which.min
##
## Attaching package: 'graph'
## The following objects are masked from 'package:igraph':
##
## degree, edges, intersection
#graphNEL objects
karateGN <- igraph.to.graphNEL(karate)
karateGN
## A graphNEL graph with undirected edges
## Number of Nodes = 34
## Number of Edges = 78
#Adjacency matrix
karateAM <- as(karateGN, "graphAM")
karateAM
## A graphAM graph with undirected edges
## Number of Nodes = 34
## Number of Edges = 78
#look at the actual adjacency matrix
karateAdjMat <- karateAM@adjMat
rownames(karateAdjMat) <- colnames(karateAdjMat)
rowSums(karateAdjMat)
## Chloe Emily Aaliyah Emma Jennifer Olivia Hannah
## 16 9 10 6 3 4 4
## Jessica Sarah Lily Charlotte Elizabeth Abigail Rebecca
## 4 5 2 3 1 2 5
## Samantha Jacob Muhammad Shawn Aaron Daniel Jonah
## 2 2 2 2 2 3 2
## Alex Michael James Ryan Jordan Alexander Ali
## 2 2 5 3 3 2 4
## Tyler Kevin Jack Ethan Luke Harry
## 3 4 4 6 12 17
colSums(karateAdjMat)
## Chloe Emily Aaliyah Emma Jennifer Olivia Hannah
## 16 9 10 6 3 4 4
## Jessica Sarah Lily Charlotte Elizabeth Abigail Rebecca
## 4 5 2 3 1 2 5
## Samantha Jacob Muhammad Shawn Aaron Daniel Jonah
## 2 2 2 2 2 3 2
## Alex Michael James Ryan Jordan Alexander Ali
## 2 2 5 3 3 2 4
## Tyler Kevin Jack Ethan Luke Harry
## 3 4 4 6 12 17
karateAdjMat
## Chloe Emily Aaliyah Emma Jennifer Olivia Hannah Jessica Sarah
## Chloe 0 1 1 1 1 1 1 1 1
## Emily 1 0 1 1 0 0 0 1 0
## Aaliyah 1 1 0 1 0 0 0 1 1
## Emma 1 1 1 0 0 0 0 1 0
## Jennifer 1 0 0 0 0 0 1 0 0
## Olivia 1 0 0 0 0 0 1 0 0
## Hannah 1 0 0 0 1 1 0 0 0
## Jessica 1 1 1 1 0 0 0 0 0
## Sarah 1 0 1 0 0 0 0 0 0
## Lily 0 0 1 0 0 0 0 0 0
## Charlotte 1 0 0 0 1 1 0 0 0
## Elizabeth 1 0 0 0 0 0 0 0 0
## Abigail 1 0 0 1 0 0 0 0 0
## Rebecca 1 1 1 1 0 0 0 0 0
## Samantha 0 0 0 0 0 0 0 0 0
## Jacob 0 0 0 0 0 0 0 0 0
## Muhammad 0 0 0 0 0 1 1 0 0
## Shawn 1 1 0 0 0 0 0 0 0
## Aaron 0 0 0 0 0 0 0 0 0
## Daniel 1 1 0 0 0 0 0 0 0
## Jonah 0 0 0 0 0 0 0 0 0
## Alex 1 1 0 0 0 0 0 0 0
## Michael 0 0 0 0 0 0 0 0 0
## James 0 0 0 0 0 0 0 0 0
## Ryan 0 0 0 0 0 0 0 0 0
## Jordan 0 0 0 0 0 0 0 0 0
## Alexander 0 0 0 0 0 0 0 0 0
## Ali 0 0 1 0 0 0 0 0 0
## Tyler 0 0 1 0 0 0 0 0 0
## Kevin 0 0 0 0 0 0 0 0 0
## Jack 0 1 0 0 0 0 0 0 1
## Ethan 1 0 0 0 0 0 0 0 0
## Luke 0 0 1 0 0 0 0 0 1
## Harry 0 0 0 0 0 0 0 0 1
## Lily Charlotte Elizabeth Abigail Rebecca Samantha Jacob Muhammad
## Chloe 0 1 1 1 1 0 0 0
## Emily 0 0 0 0 1 0 0 0
## Aaliyah 1 0 0 0 1 0 0 0
## Emma 0 0 0 1 1 0 0 0
## Jennifer 0 1 0 0 0 0 0 0
## Olivia 0 1 0 0 0 0 0 1
## Hannah 0 0 0 0 0 0 0 1
## Jessica 0 0 0 0 0 0 0 0
## Sarah 0 0 0 0 0 0 0 0
## Lily 0 0 0 0 0 0 0 0
## Charlotte 0 0 0 0 0 0 0 0
## Elizabeth 0 0 0 0 0 0 0 0
## Abigail 0 0 0 0 0 0 0 0
## Rebecca 0 0 0 0 0 0 0 0
## Samantha 0 0 0 0 0 0 0 0
## Jacob 0 0 0 0 0 0 0 0
## Muhammad 0 0 0 0 0 0 0 0
## Shawn 0 0 0 0 0 0 0 0
## Aaron 0 0 0 0 0 0 0 0
## Daniel 0 0 0 0 0 0 0 0
## Jonah 0 0 0 0 0 0 0 0
## Alex 0 0 0 0 0 0 0 0
## Michael 0 0 0 0 0 0 0 0
## James 0 0 0 0 0 0 0 0
## Ryan 0 0 0 0 0 0 0 0
## Jordan 0 0 0 0 0 0 0 0
## Alexander 0 0 0 0 0 0 0 0
## Ali 0 0 0 0 0 0 0 0
## Tyler 0 0 0 0 0 0 0 0
## Kevin 0 0 0 0 0 0 0 0
## Jack 0 0 0 0 0 0 0 0
## Ethan 0 0 0 0 0 0 0 0
## Luke 0 0 0 0 0 1 1 0
## Harry 1 0 0 0 1 1 1 0
## Shawn Aaron Daniel Jonah Alex Michael James Ryan Jordan
## Chloe 1 0 1 0 1 0 0 0 0
## Emily 1 0 1 0 1 0 0 0 0
## Aaliyah 0 0 0 0 0 0 0 0 0
## Emma 0 0 0 0 0 0 0 0 0
## Jennifer 0 0 0 0 0 0 0 0 0
## Olivia 0 0 0 0 0 0 0 0 0
## Hannah 0 0 0 0 0 0 0 0 0
## Jessica 0 0 0 0 0 0 0 0 0
## Sarah 0 0 0 0 0 0 0 0 0
## Lily 0 0 0 0 0 0 0 0 0
## Charlotte 0 0 0 0 0 0 0 0 0
## Elizabeth 0 0 0 0 0 0 0 0 0
## Abigail 0 0 0 0 0 0 0 0 0
## Rebecca 0 0 0 0 0 0 0 0 0
## Samantha 0 0 0 0 0 0 0 0 0
## Jacob 0 0 0 0 0 0 0 0 0
## Muhammad 0 0 0 0 0 0 0 0 0
## Shawn 0 0 0 0 0 0 0 0 0
## Aaron 0 0 0 0 0 0 0 0 0
## Daniel 0 0 0 0 0 0 0 0 0
## Jonah 0 0 0 0 0 0 0 0 0
## Alex 0 0 0 0 0 0 0 0 0
## Michael 0 0 0 0 0 0 0 0 0
## James 0 0 0 0 0 0 0 0 1
## Ryan 0 0 0 0 0 0 0 0 1
## Jordan 0 0 0 0 0 0 1 1 0
## Alexander 0 0 0 0 0 0 0 0 0
## Ali 0 0 0 0 0 0 1 1 0
## Tyler 0 0 0 0 0 0 0 0 0
## Kevin 0 0 0 0 0 0 1 0 0
## Jack 0 0 0 0 0 0 0 0 0
## Ethan 0 0 0 0 0 0 0 1 1
## Luke 0 1 0 1 0 1 1 0 0
## Harry 0 1 1 1 0 1 1 0 0
## Alexander Ali Tyler Kevin Jack Ethan Luke Harry
## Chloe 0 0 0 0 0 1 0 0
## Emily 0 0 0 0 1 0 0 0
## Aaliyah 0 1 1 0 0 0 1 0
## Emma 0 0 0 0 0 0 0 0
## Jennifer 0 0 0 0 0 0 0 0
## Olivia 0 0 0 0 0 0 0 0
## Hannah 0 0 0 0 0 0 0 0
## Jessica 0 0 0 0 0 0 0 0
## Sarah 0 0 0 0 1 0 1 1
## Lily 0 0 0 0 0 0 0 1
## Charlotte 0 0 0 0 0 0 0 0
## Elizabeth 0 0 0 0 0 0 0 0
## Abigail 0 0 0 0 0 0 0 0
## Rebecca 0 0 0 0 0 0 0 1
## Samantha 0 0 0 0 0 0 1 1
## Jacob 0 0 0 0 0 0 1 1
## Muhammad 0 0 0 0 0 0 0 0
## Shawn 0 0 0 0 0 0 0 0
## Aaron 0 0 0 0 0 0 1 1
## Daniel 0 0 0 0 0 0 0 1
## Jonah 0 0 0 0 0 0 1 1
## Alex 0 0 0 0 0 0 0 0
## Michael 0 0 0 0 0 0 1 1
## James 0 1 0 1 0 0 1 1
## Ryan 0 1 0 0 0 1 0 0
## Jordan 0 0 0 0 0 1 0 0
## Alexander 0 0 0 1 0 0 0 1
## Ali 0 0 0 0 0 0 0 1
## Tyler 0 0 0 0 0 1 0 1
## Kevin 1 0 0 0 0 0 1 1
## Jack 0 0 0 0 0 0 1 1
## Ethan 0 0 1 0 0 0 1 1
## Luke 0 0 0 1 1 1 0 1
## Harry 1 1 1 1 1 1 1 0
Sometimes you want to take your subgraphs and use a program like Cytoscape to make the visualization prettier.
Writing to GML format will preserve most of your information.
write_graph(karate, file="karate2.gml", format="gml")
Lots of other output options, including:
The cyREST API allows you to programatically transfer network data into Cytoscape. It’s a bit quirky to set up and use, but once you set it up, you can transfer all network attributes (edge, node, and graph) that you’ve assigned to your GraphNEL objects directly into Cytoscape.
For more info, check this link out: https://github.com/idekerlab/cy-rest-R
Rgraphviz
I used a combination of ggplot2
and Rgraphviz
to plot time-series data on a pathway defined by KEGG. To get this to work, I had to define some clusters in the graph layout.
Rgraphviz
Graphviz
is not guaranteed to give you the best layout - it can take a lot of customization and specification of clusters. You may want to take your networks into a tool such as Cytoscape that will let you customize your graph much more.
More info on customizing graph layout for Rgraphviz here: https://bioconductor.org/packages/release/bioc/vignettes/biocGraph/inst/doc/layingOutPathways.pdf
visNetwork
Make interactive networks with visNetwork
and shiny
!
Why would you want to do this? Exploratory Data Analysis of the Network.
library(igraph)
karate <- read_graph("data/karate.gml", format="gml")
karate <- set.vertex.attribute(karate, "name",
value=c("Chloe", "Emily", "Aaliyah", "Emma",
"Jennifer", "Olivia", "Hannah",
"Jessica", "Sarah", "Lily", "Charlotte",
"Elizabeth", "Abigail", "Rebecca",
"Samantha", "Jacob", "Muhammad", "Shawn",
"Aaron", "Daniel", "Jonah", "Alex",
"Michael", "James", "Ryan", "Jordan",
"Alexander", "Ali", "Tyler", "Kevin",
"Jack", "Ethan", "Luke", "Harry"))
deg <- igraph::degree(karate)
kInt <- toVisNetworkData(karate)
nodes <- kInt$nodes
nodes$label <- rownames(nodes)
nodes$id <- rownames(nodes)
edges <- kInt$edges
output$network <- renderVisNetwork({
# minimal example
visNetwork(nodes, edges, height="600px", width="100%") %>%
visOptions(highlightNearest = TRUE) %>%
visInteraction(navigationButtons = TRUE)
})
observe({
nodes_selection <- names(deg[deg >= min(input$slide_me) & deg <= max(input$slide_me)])
print(names(nodes_selection))
print(nodes_selection)
visNetworkProxy("network") %>%
visSelectNodes(id = nodes_selection,highlightEdges = TRUE,clickEvent = TRUE)
})
visNetwork
objects and igraph
objectsI used toVisNetworkData()
to convert my igraph
karate
object to a visNetwork object:
kInt <- toVisNetworkData(karate)
#need to relabel nodes data.frame
nodes <- kInt$nodes
nodes$label <- rownames(nodes)
nodes$id <- rownames(nodes)
edges <- kInt$edges
visNetwork(nodes, edges, height="600px", width="100%")
sessionInfo()
## R version 3.3.3 (2017-03-06)
## Platform: x86_64-apple-darwin13.4.0 (64-bit)
## Running under: macOS Sierra 10.12.6
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] parallel stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] graph_1.52.0 BiocGenerics_0.20.0 shiny_1.0.5
## [4] visNetwork_2.0.1 knitr_1.17 igraph_1.0.1
## [7] gridExtra_2.3
##
## loaded via a namespace (and not attached):
## [1] Rcpp_0.12.12 magrittr_1.5 xtable_1.8-2 R6_2.2.2
## [5] stringr_1.2.0 tools_3.3.3 grid_3.3.3 gtable_0.2.0
## [9] htmltools_0.3.6 yaml_2.1.14 rprojroot_1.2 digest_0.6.12
## [13] htmlwidgets_0.9 evaluate_0.10.1 mime_0.5 rmarkdown_1.6
## [17] stringi_1.1.5 backports_1.0.5 stats4_3.3.3 jsonlite_1.5
## [21] httpuv_1.3.5