iGraph + Plotly creates random connections - r

I'm trying to use the example code here for doing iGraph network graphs in plotly and shoehorn in my own data.frames instead of using the example karate club data. When the graph is plotted, it seems to ignore the edge list and a bunch of random connections are being made. I think either the labels or edges are wrong but I can't tell.
library(igraph)
library(plotly)
setwd('C:/Users/Andrew Riffle/Documents/MEGAsync/code/R/link_analysis')
ID <- c(1:50)
nodes <- data.frame(ID)
Source <- c(23, 24, 36, 20, 36, 41, 12, 8, 18, 28)
Target <- c(5, 7, 9, 35, 23, 12, 38, 29, 33, 45)
links <- data.frame(Source, Target)
net <- graph_from_data_frame(d=links, vertices=nodes, directed=FALSE)
net <- simplify(net, remove.multiple = F, remove.loops = T)
tkplot(net, vertex.label=nodes$id, vertex.label.color='white', layout=layout.fruchterman.reingold)
#####Begin plotly example code unmodified unless commented#####
G <- upgrade_graph(net) #put my iGraph object instead of the karate club one
L <- layout.circle(G)
vs <- V(G)
es <- as.data.frame(get.edgelist(G))
Nv <- length(vs)
Ne <- length(es[1]$V1)
Xn <- L[,1]
Yn <- L[,2]
network <- plot_ly(x = ~Xn, y = ~Yn, mode = "markers", text = vs$name, hoverinfo = "text")
edge_shapes <- list()
for(i in 1:Ne) {
v0 <- es[i,]$V1
v1 <- es[i,]$V2
edge_shape = list(
type = "line",
line = list(color = "#030303", width = 0.3),
x0 = Xn[v0],
y0 = Yn[v0],
x1 = Xn[v1],
y1 = Yn[v1]
)
edge_shapes[[i]] <- edge_shape
}
axis <- list(title = "", showgrid = FALSE, showticklabels = FALSE, zeroline = FALSE)
p <- layout(
network,
title = 'Test Network', #Changed the title
shapes = edge_shapes,
xaxis = axis,
yaxis = axis
)
p #added a call to display p instead of upload to plot.ly
When I run this, I get this nice pretty iGraph that has been plotted by Plotly. However, the edges are incorrect. It appears that only the ID's 1-10 are connecting, and only to other ID's less than 10. None of these connections is in the edge list, which is below.
Source Target
1 24 35
2 12 23
3 41 12
4 23 7
5 18 5
6 20 9
7 28 29
8 36 45
9 8 33
10 36 38
Does anyone see what I'm doing wrong? Help appreciated.

I know it's a bit too late for the OP, but for the others who stumbled upon this same problem (as did I).
May I suggest the following five changes in the tutorial source code:
G <- upgrade_graph(net)
L <- layout.circle(G)
rownames(L) <- get.vertex.attribute(G)$name #added line (#1 out of 5)
vs <- V(G)
es <- as.data.frame(get.edgelist(G))
Nv <- length(vs)
Ne <- length(es[1]$V1)
Xn <- L[,1]
Yn <- L[,2]
network <- plot_ly(x = ~Xn, y = ~Yn, mode = "markers", text = vs$name, hoverinfo = "text")
edge_shapes <- list()
for(i in 1:Ne) {
v0 <- es[i,]$V1
v1 <- es[i,]$V2
edge_shape = list(
type = "line",
line = list(color = "#030303", width = 0.3),
x0 = L[which(v0==rownames(L)),][1], #changed line (#2 out of 5)
y0 = L[which(v0==rownames(L)),][2], #changed line (#3 out of 5)
x1 = L[which(v1==rownames(L)),][1], #changed line (#4 out of 5)
y1 = L[which(v1==rownames(L)),][2] #changed line (#5 out of 5)
)
edge_shapes[[i]] <- edge_shape
}
axis <- list(title = "", showgrid = FALSE, showticklabels = FALSE, zeroline = FALSE)
p <- layout(
network,
title = 'Test Network', #Changed the title
shapes = edge_shapes,
xaxis = axis,
yaxis = axis
)
p
Works fine now.

Discovered that the tutorial is actually wrong. If you plot the same karate network using plot compared to using plotly, there are many connections in plot that aren't in plotly.
I've given up trying to make this work, visNetwork is an excellent alternative that I've had a much easier time figuring out. Recommend that for anyone with a similar issue reading this.

Related

Error: x,y coords given but no window specified (spatstat)

I am generating a landscape pattern that evolves over time. The problem with the code is that I have clearly defined a window for the object bringing up the error but the window is not being recognised. I also do not see how any points are falling outside of the window, or how that would make a difference.
library(spatstat)
library(dplyr)
# Define the window
win <- owin(c(0, 100), c(0, 100))
# Define the point cluster
cluster1 <- rMatClust(kappa = 0.0005, scale = 0.1, mu = 20,
win = win, center = c(5,5))
# define the spread of the points
spread_rate <- 1
new_nests_per_year<-5
years<-10
# Plot the initial cluster
plot(win, main = "Initial cluster")
points(cluster1, pch = 20, col = "red")
newpoints<-list()
# Loop for n years
for (i in 1:years) {
# Generate new points that spread from the cluster
newpoints[[1]] <-rnorm(new_nests_per_year, mean = centroid.owin(cluster1)$y, sd = spread_rate)
newpoints[[2]] <-rnorm(new_nests_per_year, mean = centroid.owin(cluster1)$x, sd = spread_rate)
# Convert the list to a data frame
newpoints_df <- data.frame(newpoints)
# Rename the columns of the data frame
colnames(newpoints_df) <- c("x", "y")
# Combine the new points with the existing points
cluster1_df <- data.frame(cluster1)
newtotaldf<-bind_rows(cluster1_df,newpoints_df)
cluster1<-as.ppp(newtotaldf, x = newtotaldf$x, y = newtotaldf$y,
window = win)
# Plot the updated cluster
plot(win, main = paste("Cluster after year", i))
points(cluster1, pch = 20, col = "red")
}
However, when I run line:
cluster1<-as.ppp(newtotaldf, x = newtotaldf$x, y = newtotaldf$y,
window = win)
I recieve the error:
Error: x,y coords given but no window specified
Why would this be the case?
In your code, if you use the command W = win it should solve the issue. I also believe you can simplify the command without specifying x and y:
## ...[previous code]...
cluster1 <- as.ppp(newtotaldf, W = win)
plot(win)
points(cluster1, pch = 20, col = "red")

Multi-panel network figure using a loop?

I'm trying to make a multipanel figure with networks in the igraph package. I'd like 2 rows, each with 3 networks. I need to be able to save the figure as a PNG and I'd like to label them each A:F in one of the corners. I've tried to do this in a loop but only one network appears in the figures. I need the V(nw)$x<- y and E(nw)$x<- y code in the loop to make my networks come out properly. My networks are in a list().
I've made a small sample of the code I've tried, I would like to avoid doing it without a loop if I can. Thanks in advance.
srs_1nw <- graph("Zachary")
srs_2nw <- graph("Heawood")
srs_3nw <- graph("Folkman")
srs_1c <- cluster_fast_greedy(srs_1nw)
srs_2c <- cluster_fast_greedy(srs_2nw)
srs_3c <- cluster_fast_greedy(srs_3nw)
listofsrs_nws <- list(srs_1nw,srs_2nw,srs_3nw)
listofsrs_cs <- list(srs_1c,srs_2c,srs_3c)
colours <- c("red","blue","green","yellow")
par(mfrow=c(2,3))
for (i in length(listofsrs_nws)) {
c<-listofsrs_cs[[i]]
nw<-listofsrs_nws[[i]]
V(nw)$size <- log(strength(nw))*6 # weighted nodes
E(nw)$arrow.size <- 2 # arrow size
c.colours <- colours[membership(c)]
plot(c, nw, col = c.colours,
mark.col = adjustcolor(colours, alpha.f = 0.4),
mark.border = adjustcolor(colours, alpha.f = 1),
vertex.frame.width = 5, edge.curved = .15)
}
We can use mapply like below
mapply(function(c, nw) {
V(nw)$size <- log(strength(nw)) * 6 # weighted nodes
E(nw)$arrow.size <- 2 # arrow size
c.colours <- colours[membership(c)]
plot(c, nw,
col = c.colours,
mark.col = adjustcolor(colours, alpha.f = 0.4),
mark.border = adjustcolor(colours, alpha.f = 1),
vertex.frame.width = 5, edge.curved = .15
)
}, listofsrs_cs, listofsrs_nws)

plotly Sankey diagram: Can I make 4 or more links between two nodes?

I created a Sankey diagram using the plotly package.
Please look at below example. I tried to make five streams, 1_6_7, 2_6_7, and so on. But two of five links between 6 and 7 disappeared. As far as I see, plotly allows to make only three or less links between two nodes.
Can I remove this restrictions ? Any help would be greatly appreciated.
Here is an example code and the outputs:
d <- expand.grid(1:5, 6, 7)
node_label <- 1:max(d)
node_colour <- scales::alpha(RColorBrewer::brewer.pal(7, "Set2"), 0.8)
link_source_nodeind <- c(d[,1], d[,2]) - 1
link_target_nodeind <- c(d[,2], d[,3]) - 1
link_value <- rep(100, nrow(d) * 2)
link_label <- rep(paste(d[,1], d[,2], d[,3], sep = "_"), 2)
link_colour <- rep(scales::alpha(RColorBrewer::brewer.pal(5, "Set2"), 0.2), 2)
p <- plotly::plot_ly(type = "sankey",
domain = c(x = c(0,1), y = c(0,1)),
orientation = "h",
node = list(label = node_label,
color = node_colour),
link = list(source = link_source_nodeind,
target = link_target_nodeind,
value = link_value,
label = link_label,
color = link_colour))
p

Error of self edges in hive plot

Absolutely cannot figure out why the error is coming even though there are no self edges.
Below is a reproducible code. Any help would be great
library(HiveR)
nodes = data.frame(id = 1:9, lab = c("A","B","C","E","F","G","H","I","J"),
axis = c(1,1,1,2,3,2,2,2,3), radius = rep(50,9),size = rep(10,9),
color = c("yellow","yellow","yellow", "green","red","green","green","green","red"))
edges = data.frame(id1 = c(1,2,3,4,5,4,1,9,8,6,1),id2 = c(2,3,4,1,9,9,9,8,7,7,6),
weight = rep(1,11),
color = c(rep("green",7), rep("red",4)))
test3 <- ranHiveData(nx = 3)
test3$nodes = nodes
test3$edges = edges
test3$edges$color <- as.character(test3$edges$color)
test3$edges$id1 <- as.integer(test3$edges$id1)
test3$edges$id2 <- as.integer(test3$edges$id2)
test3$nodes$color <- as.character(test3$nodes$color)
test3$nodes$lab <- as.character(test3$nodes$lab)
test3$nodes$axis = as.integer(test3$nodes$axis)
test3$nodes$id = as.integer(test3$nodes$id)
test3$nodes$radius = as.numeric(test3$nodes$radius)
test3$nodes$size = as.numeric(test3$nodes$size)
test3$edges$weight = as.numeric(test3$edges$weight)
test3$desc = "3 axes --9 nodes -- 11 edges"
sumHPD(test3, chk.sm.pt = TRUE)
The code is giving self edges and the the plot is not rendering plotHive(test3) showing
Error in calcCurveGrob(x,x$debug) : end points must not be identical
In your code the position of the nodes of the axis (radius) are all set to 50. Hence there are overlapping points (3 on axis 1, 4 on axes 2 and 2 on axis 3).
A correct definition of radius solves the problem.
library(HiveR)
# radius has been changed !
nodes = data.frame(id = 1:9, lab = c("A","B","C","E","F","G","H","I","J"),
axis = c(1,1,1,2,3,2,2,2,3), radius = c(1,2,3,1,1,2,3,4,2),size = rep(1,9),
color = c("yellow","yellow","yellow", "green","red","green","green","green","red"))
edges = data.frame(id1 = c(1,2,3,4,5,4,1,9,8,6,1),id2 = c(2,3,4,1,9,9,9,8,7,7,6),
weight = rep(1,11),
color = c(rep("green",7), rep("red",4)))
test3 <- ranHiveData(nx = 3)
test3$nodes = nodes
test3$edges = edges
test3$edges$color <- as.character(test3$edges$color)
test3$edges$id1 <- as.integer(test3$edges$id1)
test3$edges$id2 <- as.integer(test3$edges$id2)
test3$nodes$color <- as.character(test3$nodes$color)
test3$nodes$lab <- as.character(test3$nodes$lab)
test3$nodes$axis = as.integer(test3$nodes$axis)
test3$nodes$id = as.integer(test3$nodes$id)
test3$nodes$radius = as.numeric(test3$nodes$radius)
test3$nodes$size = as.numeric(test3$nodes$size)
test3$edges$weight = as.numeric(test3$edges$weight)
test3$desc = "3 axes --9 nodes -- 11 edges"
sumHPD(test3, chk.sm.pt = TRUE)
plotHive(test3)

graph parameters to change node size and node text font size

Assuming I am creating a directed graph as follows
a = sample(state.name, 10)
b = sample(state.name, 10)
c = sample(state.name, 10)
d = data.frame(a,b,c)
d1 = as.matrix(d)
edges1 = rbind(d1[,1:2],d1[,2:3])
g = graph.data.frame(edges1, directed=F)
adj <- as.matrix(get.adjacency(g))
g2 <- new("graphAM", adjMat=adj, edgemode="directed")
plot(g2, attrs = list(graph = list(rankdir="LR"),
node = list(fillcolor = "lightblue")))
I get a very ugly graph with very disproportionate node size and node text. (sorry dont have enough credit to post the image of the graph)
I tried node.size and V(g).size parameters and it didnt work. Any advise ?

Resources