thomasp85/ggraph

Swapping of "from" and "to" axes in directed hive plots

ctross opened this issue · 1 comments

Great work on this package. Its the only code for R that I have found that lets me nicely visualize network data. I did seem to find some unexpected behavior, however.

The hive plot seems to do some weird swapping of the "from" and "to" columns when plotting directed network data.

Below is the simplest example to show the problem.

The example is designed to show the effect of simply changing the order of the variable used to sort the nodes.
If Z is a sorting variable then defining Z2 = -1*Z should only invert the order of the axis. However, it also seems to flip which axis is "from" and which is "to".

Any easy fixes? Could we at least label the two axis as "to" and "from" for hive plots with loops?

Thanks!

###############

library(devtools)
install_github('ctross/STRAND') # To make the fake network data 
library(STRAND)

library(igraph)
library(ggraph)

############################################ Make network data
N_id = 100
A = simulate_srm_network(N_id = N_id, B=-8, 
                         individual_predictor=matrix(rnorm(N_id, 0, 1), nrow=N_id, ncol=1), 
                         individual_effects=matrix(c(3, 0), ncol=1, nrow=2),                                #Ties are more likely to be sent by people high in generosity (the param 3 controls this), and equally likely to hit any recipient (the param 0 controls this)
                         sr_sigma = c(1.4, 0.8), sr_rho = 0.5,
                         dr_sigma = 1.2, dr_rho = 0.8,
                         mode="bernoulli"
                         )
Net = graph_from_adjacency_matrix(A$network, mode = c("directed"))

plot(Net, edge.arrow.size =0.1, edge.curved = 0.3, vertex.label=NA, vertex.size = 5)


##################### now Hive plot
Give = A$network 
colnames(Give)=rownames(Give)=paste0("Bob",1:100)

diag(Give)=0

gq1 = graph_from_adjacency_matrix(Give) 
d_g2 = get.data.frame(gq1)

d_g2$Layer = "Give"

Generous = A$individual_predictor[,1]
names(Generous)=paste0("Bob",1:100)

d_all = rbind(d_g2)
d_all = d_all[which(d_all$from %in% names(Generous) & d_all$to %in% names(Generous)),]

#######################################################
d_all_r = d_all[which(d_all$Layer == "Give"),]

graph <- graph_from_data_frame(d_all_r, directed=TRUE, vertices=names(Generous))

Standing = Generous

V(graph)$Standing <- as.character(ifelse(Standing>1,"High",ifelse(Standing < -1, "Low","Average")))
V(graph)$indeg <- Standing #igraph::degree(graph, mode = 'out')
V(graph)$layer <- rep("Giving",length(Standing))

X = 30

P1 = ggraph(graph, 'hive', axis = layer, sort.by = indeg, normalize=FALSE,use.numeric=FALSE,split.axes="all",split.angle=1,center.size=1,divide.by=Standing, divide.order=c("Low","Average","High")) + 
    geom_edge_hive(color = "#3e3131", alpha=0.18, strength=1) + 
    geom_axis_hive(aes(color = Standing), size = 3) + 
    coord_fixed() + theme(legend.position="none") + 
    facet_wrap(~layer) + theme(strip.text.x = element_text(size = X+2), legend.text = element_text(size = X), legend.title = element_text(size = X))  +
    scale_colour_manual(values = c( "High" = "#eb781b", "Average" = "#cc5221", "Low" = "#71250e"),name = "Standing:")
P1
#### P1 looks perfect, ties flow out on the left from generous people, and hit all others at equal density on the right
windows()

#######################################################
d_all_r = d_all[which(d_all$Layer == "Give"),]

graph <- graph_from_data_frame(d_all_r, directed=TRUE, vertices=names(Generous))

Standing = Generous*-1 ## This is the key change. Flipping the order of the sorting variable should invert the figure, but NOT swap the left and right axis

V(graph)$Standing <- as.character(ifelse(Standing>1,"High",ifelse(Standing < -1, "Low","Average")))
V(graph)$indeg <- Standing #igraph::degree(graph, mode = 'out')
V(graph)$layer <- rep("Giving",length(Standing))

X = 30

P2 = ggraph(graph, 'hive', axis = layer, sort.by = indeg, normalize=FALSE,use.numeric=FALSE,split.axes="all",split.angle=1,center.size=1,divide.by=Standing, divide.order=c("Low","Average","High")) + 
    geom_edge_hive(color = "#3e3131", alpha=0.18, strength=1) + 
    geom_axis_hive(aes(color = Standing), size = 3) + 
    coord_fixed() + theme(legend.position="none") + 
    facet_wrap(~layer) + theme(strip.text.x = element_text(size = X+2), legend.text = element_text(size = X), legend.title = element_text(size = X))  +
    scale_colour_manual(values = c( "High" = "#eb781b", "Average" = "#cc5221", "Low" = "#71250e"),name = "Standing:")
P2

# P2 look wacky, as the left column is now the "to" column, but it should be "from"

This is a bit belated but can you provide a more minimal reprex. I'm not able to install STRAND