Search code examples
rggplot2ggraph

Map coordinates of connections with to and from vertices names


I am trying to figure out a way to map coordinates generated through geom_conn_bundle with the vertices name of the graph. Following is the sample data and my implementation:

d1 <- data.frame(from="origin", to=paste("Dept", seq(1,5), sep=""))
d1 <- rbind(d1,c('origin','application'))
d2<-data.frame(from=c('Dept1','Dept2','Dept3','Dept4','Dept5','application','application','application'),to=c('[email protected]','[email protected]','[email protected]','[email protected]','[email protected]','App1','App2','App3'))
edges <-rbind(d1,d2)
d1<- data.frame(from='origin',to=paste("Dept",seq(1,5),sep=""))
d_1 <- data.frame(from=rep(d1$to,each=5),to=paste(paste('email',seq(1,100),sep=""),'@abc.com',sep=""))
d_1<-sample_n(d_1, 20)

d_2 <- data.frame(from=rep('application',each=5),to=paste('App',seq(1,100),sep=""))
d_2<-sample_n(d_2, 20)


d1 <- rbind(d1,c('origin','application'))

d2<-rbind(d_1,d_2)
edges <-rbind(d1,d2)
all_leaves<- unique(d2$to)

connect<- rbind(
  data.frame(from=sample(head(d_1$to),15,replace=T), to=sample(tail(d_2$to),15,replace=T)),
  data.frame(from=sample(tail(d_1$to),15,replace=T), to=sample(head(d_2$to),15,replace=T)),
  data.frame(from=sample(d_1$to,15,replace=T), to=sample(d_2$to,15,replace=T)),
  data.frame(from=sample(d_1$to,15,replace=T), to=sample(d_2$to,15,replace=T))
)
connect$value <- runif(nrow(connect))
#connect

vertices  <-  data.frame(
  name = unique(c(as.character(edges$from), as.character(edges$to)))
)
vertices$value <-runif(nrow(vertices))
vertices$group <-edges$from[ match( vertices$name, edges$to ) ]

vertices$id <- NA
myleaves <- which(is.na(match(vertices$name, edges$from) ))
nleaves <- length(myleaves)
vertices$id[ myleaves ] <- seq(1:nleaves)
vertices$angle <- 90 - 360 * vertices$id / nleaves

# calculate the alignment of labels: right or left
# If I am on the left part of the plot, my labels have currently an angle < -90
vertices$hjust <- ifelse( vertices$angle < -90, 1, 0)

# flip angle BY to make them readable
vertices$angle <- ifelse(vertices$angle < -90, vertices$angle+180, vertices$angle)

mygraph <- igraph::graph_from_data_frame( edges, vertices=vertices )

# The connection object must refer to the ids of the leaves:
from  <-  match( connect$from, vertices$name)
to  <-  match( connect$to, vertices$name)
options(repr.plot.width=15, repr.plot.height=8)
# Basic usual argument
p<-ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
  geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05,colour=group, size=value, alpha=0.2)) +
  geom_conn_bundle(data = get_con(from = from, to = to), alpha=0.2, colour="skyblue", width=0.9) +
  geom_node_text(aes(x = x*1.1, y=y*1.1, filter = leaf, label=name, angle = angle, hjust=hjust), size=4, alpha=1.5) +

  theme_void() +
  theme(
    legend.position="none",
    plot.margin=unit(c(0,0,0,0),"cm"),
  ) +
 expand_limits(x = c(1, 1), y = c(1, 1))
#expand_limits(x = c(-1.2, 1.2), y = c(-1.2, 1.2))
p
pg <- ggplot_build(p)

I would like to get to and from vertices names for each coordinate calculated through geom_conn_bundle which can be access by

pg[[1]][[2]]

Solution

  • You just need to translate them back from the group column using the from and to vectors:

    conn.points <- pg[[1]][[2]]
    conn.points$from_name <- vertices$name[from[conn.points$group]]
    conn.points$to_name <- vertices$name[to[conn.points$group]]
    

    A simple test to see if it works:

    p + geom_point(aes(x=x, y=y), data=subset(
      conn.points, from_name=='[email protected]' & to_name=='App4'))
    

    graph