Convert ggraph to interative plot with plotyly or Network3D - r

I was looking for an example or tutorial to convert a ggraph object to an iterative force network.
First I tried to convert to plotly object using plotly::ggplotly function. But seems the plotly don't deal nicely with this kind of conversion and miss the edges.
But I find the network3D, I can convert an igraph object to a network3D object, but it is not what I wanted. And this package has too verbose functions. Anyway, there is no function to convert from ggraph object.
So, my question is really basic but... Do you know any method to crate an interactive ggraph network?
Thanks

Try the ggiraph package, it works with ggraph as you can see in the example here (bottom of the page).
For future reference (if the above link may die), here's the example of ggiraph (not my code):
library(ggraph)
library(igraph)
library(ggiraph)
actors <- data.frame(
name = c("Alice", "Bob", "Cecil", "David", "Esmeralda"),
age = c(48,33,45,34,21),
gender = c("F","M","F","M","F")
)
relations <- data.frame(
from = c("Bob", "Cecil", "Cecil", "David", "David", "Esmeralda"),
to = c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
same.dept = c(FALSE,FALSE,TRUE,FALSE,FALSE,TRUE),
friendship = c(4,5,5,2,1,1),
advice = c(4,5,5,4,2,3)
)
g <- graph_from_data_frame(relations,
directed = TRUE, vertices = actors)
z <- ggraph(g, layout = 'linear', circular = TRUE) +
geom_edge_arc(color = "red", edge_width = .2) +
geom_point_interactive(size = 5,
mapping = aes(x = x, y = y, data_id = gender,
tooltip = paste0(name, ": ", age, "y.o."))
) + theme_graph()
girafe(ggobj = z, width_svg = 5, height_svg = 5,
options = list(opts_sizing(rescale = FALSE)))
It seems plotly does not support ggraph yet, but you can track the progress here.

Related

Change edge thickness according to a column of a dataframe containing relations between actors

This code plots a graph from dataframes of actors and relations.
library(igraph)
actors <- data.frame(name=c("Alice", "Bob", "Cecil", "David",
"Esmeralda"))
relations <- data.frame(from=c("Bob", "Cecil", "Cecil", "David",
"David", "Esmeralda"),
to=c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
friendship=c(4,15,5,2,11,1))
g <- graph_from_data_frame(relations, directed=TRUE, vertices=actors)
plot(g)
The result is:
I would like to change the thickness (not the length) of the arcs based on the value of relations$friendship.
Try
plot(g,edge.width = E(g)$friendship, edge.arrow.size = E(g)$friendship)
Note that, the first value of E(g)$friendship is assigned to edge.arrow.size, instead of a vector. Maybe the improved feature will be added to future igraph version.
arrow.size The size of the arrows. Currently this is a constant, so it
is the same for every edge. If a vector is submitted then only the
first element is used, ie. if this is taken from an edge attribute
then only the attribute of the first edge is used for all arrows. This
will likely change in the future.
The default value is 1.
arrow.width The width of the arrows. Currently this is a constant, so
it is the same for every edge. If a vector is submitted then only the
first element is used, ie. if this is taken from an edge attribute
then only the attribute of the first edge is used for all arrows. This
will likely change in the future.
This argument is currently only used by plot.igraph.
The default value is 1, which gives the same width as before this
option appeared in igraph.
This can be achieved very simply.
First your code:
library(igraph)
actors <- data.frame(name=c("Alice", "Bob", "Cecil", "David",
"Esmeralda"))
relations <- data.frame(from=c("Bob", "Cecil", "Cecil", "David",
"David", "Esmeralda"),
to=c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
friendship=c(4,15,5,2,11,1))
g <- graph_from_data_frame(relations, directed=TRUE, vertices=actors)
Now let's create a graph with a thickness of 2, line color black and line type 2.
plot(g, edge.width = 2, edge.color = "black", edge.lty = 2)
Of course, you can change it as you like
plot(g, edge.width = 5, edge.color = "black", edge.lty = 1)
Hope that's what you meant.
Small update
Finally, you may want to find the coordinates of the elements. You can do it this way:
coords = layout_nicely(g)
coords[5,]=c(20, 20)
coords
output
[,1] [,2]
[1,] 15.21285 18.97650
[2,] 15.18511 20.08411
[3,] 14.21575 19.70269
[4,] 16.17453 19.75255
[5,] 20.00000 20.00000
Plot
plot(g, layout=coords, edge.width = 5, edge.color = "black", edge.lty = 1)
You can also set other cutout attributes
plot(g, vertex.size = 20, vertex.color = "red", vertex.shape = "square",
edge.width = 3, edge.color = "black", edge.lty = 3,
edge.label = relations$friendship, edge.curved = TRUE)
Also note that any of these parameters can also come from a vector.
So there is no obstacle for the thickness to come from the variable friendship, for example.
plot(g, vertex.size = 20, vertex.color = "red",
vertex.shape = c("square","circle","square","circle","rectangle"),
edge.width = relations$friendship, edge.color = "black", edge.lty = c(1,2,3,1,2,3),
edge.label = 10:20, edge.curved = TRUE)

How to make a star plot with igraph?

I am working with igraph for the first time and would like to do a "star plot"(make_star()) with the package igraph.
For this I have prepared a sample data set, it has two columns: name and wght.
I want "ME" to be in the center of the plot and all arrows should go out of it. It would be great if the arrow width corresponded to the values ​​from wght (maybe with edge.width) OR the weights on the arrows.
My code looks like this:
library(igraph)
wght <- runif(6, min = 1, max = 10)
name <- c("John", "Jim", "Jack", "Jesse", "Justin", "Peter")
data <- data.frame(name, wght)
st <- make_star(n = 6, mode = "out")
plot(st, vertex.label = data$name)
Output:
what I want:
Create a graph where "Me" is included as a vertex. Add edge attribute "weight". Create star layout with "Me" as center. Set edge widths according to weights. Plot!
g <- graph_from_data_frame(data.frame(from = "Me", to = name))
E(g)$weights <- wght
plot(g, layout = layout_as_star(g, center = V(g)["Me"]), edge.width = E(g)$weights)
Data
set.seed(1)
wght <- runif(6, min = 1, max = 10)
name <- c("John", "Jim", "Jack", "Jesse", "Justin", "Peter")
Fun to learn about a new package. This should do it for you:
st <- make_star(n=6,mode = "out") %>%
set_vertex_attr("label", index = 1, value = "ME") %>%
set_vertex_attr("label", index = 2:6, value = name[2:6])
plot(st)

Trouble creating lists in R for the networkD3 package

I'd like to create the radial network above utilizing the R package networkD3. I read the guide here which utilizes lists to create radial networks. Unfortunately my R skills with lists are lacking. They're actually non-existent. Fortunately there's the R4DS guide here.
After reading everything I come up with this code below, to create the diagram above.
library(networkD3)
nd3 <- list(Start = list(A = list(1, 2, 3), B = "B"))
diagonalNetwork(List = nd3, fontSize = 10, opacity = 0.9)
Alas, my attempt fails. And subsequent attempts fail to generate anything that's close to the diagram above. I'm pretty sure it's my list that's wrong. Maybe you can show me the right list and things will start to make sense.
Jason!
The issue here is that the parameter nd3 has a very specific grammar of node name and children. So your code should look like this:
library(networkD3)
nd3 <- list(name = "Start", children = list(list(name = "A",
children = list(list(name = "1"),
list(name = "2"),
list(name = "3")
)),
list(name = "B")))
diagonalNetwork(List = nd3, fontSize = 10, opacity = 0.9)
If you're like me and the data frame/spreadsheet format is easier to wrap your head around, you could build an easy data frame with your data and then use data.tree functions to convert it to the list/json format...
library(data.tree)
library(networkD3)
source <- c("Start", "Start", "A", "A", "A")
target <- c("A", "B", "1", "2", "3")
df <- data.frame(source, target)
nd3 <- ToListExplicit(FromDataFrameNetwork(df), unname = T)
diagonalNetwork(List = nd3, fontSize = 10, opacity = 0.9)

Combining/Merging two graphs in igraph

I created the following two graphs using igraph:
t1terms <- c("fire",
"people",
"residents",
"victims",
"affected",
"please",
"can",
"london",
"support",
"survivors")
t1labels <- as.vector(t1terms)
g<-graph.full(n=10, directed = FALSE, loops = FALSE) %>%
set_vertex_attr("label", value = t1labels)
t2terms <- c("fire",
"victims",
"says",
"people",
"cladding",
"police",
"may",
"will",
"dead",
"theresa")
t2labels <- as.vector(t2terms)
g1<-graph.full(n=10, directed = FALSE, loops = FALSE) %>%
set_vertex_attr("label", value = t2labels)
I can't figure out how to merge the two graphs without duplicating common nodes. I really appreciate some help. I tried 'graph.union', but it didn't work.
Thank you,
Chamil
Use igraph's built-in conventions and make the vertex labels into each's name:
V(g)$name <- V(g)$label
V(g1)$name <- V(g1)$label
Grab the attributes and edge list of each graph and rbind() them together, creating a combination attribute data.frame and combination edge list data.frame while ensuring that you're only keeping unique() vertices:
attrs <- rbind(as_data_frame(g, "vertices"), as_data_frame(g1, "vertices")) %>% unique()
el <- rbind(as_data_frame(g), as_data_frame(g1))
Use attrs and el to make your new graph:
new_g <- graph_from_data_frame(el, directed = FALSE, vertices = attrs)
You can get the union by turning each graph into an edgelist, joining the edgelists and the making that into a graph.
EL = matrix(get.vertex.attribute(g, "label")[get.edgelist(g)], ncol=2)
EL1 = matrix(get.vertex.attribute(g1, "label")[get.edgelist(g1)], ncol=2)
ELU = rbind(EL, EL1)
ELU = ELU[!duplicated(ELU),]
GU = graph_from_edgelist(ELU, directed=FALSE)
## To check the result
par(mfrow=c(1,3))
plot(g)
plot(g1)
plot(GU)

How can I render a networkDynamic network using the MDSJ rendering engine in R?

I would like to render a dynamic network in R using the fast MDSJ library. Unfortunately, however, all the vertices' coordinates seem to be 0,0 using this rendering engine, which is not the case when using one of the other layouts (kamadakawai or Graphviz. If you paste the code below, you should be able to reproduce the problem.
if (!require("pacman")) install.packages("pacman")
library("pacman")
pacman::p_load(network, networkDynamic, ndtv)
#animation.mode = "MDSJ"
#animation.mode = "Graphviz"
animation.mode = "kamadakawai"
people <- c("A","B","C","D","E")
documents <- paste0("a",1:10)
edges <- data.frame(from = c("A","A","A","B","B","C","D"),
to = c("a1","a2","a3","a4","a5","a1","a1"),
active = c(1,2,3,3,4,4,4))
net <- network.initialize(0, directed = TRUE, bipartite = length(people))
add.vertices.networkDynamic(net, 5, vertex.pid = people)
add.vertices.networkDynamic(net, 10, vertex.pid = documents)
net %v% "vertex.names" <- c(people, documents)
net %v% "vertex.col" <- c(rep("blue", length(people)), rep("gray", length(documents)))
set.network.attribute(net,'vertex.pid','vertex.names')
add.edges.networkDynamic(net,
tail = get.vertex.id(net, edges[[1]]),
head = get.vertex.id(net, edges[[2]]),
edge.pid = paste0(edges[[1]], "->", edges[[2]]))
activate.edges(net, e = 1:7, at = edges[[3]])
reconcile.vertex.activity(net = net, mode = "encompass.edges", edge.active.default = FALSE)
slice.par <- list(start = 1, end = 4, interval = 1, aggregate.dur = 2, rule = "earliest")
compute.animation(net,
animation.mode = animation.mode,
slice.par = slice.par)
render.d3movie(net,
slice.par = slice.par,
displaylabels = TRUE,
output.mode = "htmlWidget",
vertex.col = 'vertex.col')
Using kamadakawai, one gets a dynamic view like this:
Using MDSJ, all slides look like this:
This code works on my system with MDSJ. Does it install correctly on yours? When it's first used, it has to download and install a Java application mdsj.jar.

Resources