I am trying to draw following graph in ggraph
.
igraph
class object is obtained from a data frame below:
edge <- data.frame(from=c(0,0,0,0,1,2,3),
to=c(0,1,2,3,0,0,0),
weight=c(1,3,1,1,3,1,1))
node <- data.frame(id=c(0,1,2,3),
p=c(9,1,0,0),
w=c(0,2,0,0),
s=c(0,0,1,1),
size=c(9,3,1,1),
gr=c(0,1,1,2))
# Convert data frame into igraph class object
net <- graph_from_data_frame(d=edge,vertices=node,directed=TRUE)
However, when I draw the graph in the following scripts, it produces unexpected width of edges:
## Set arrows
ar <- arrow(angle=30,length=unit(5,"mm"),ends="last",type="closed")
## Plot
ggraph(net,layout="graphopt") +
## Edges
geom_edge_link(aes(width=weight,label=weight,
start_cap=circle(node1.size+1,unit="native"),
end_cap=circle(node2.size+1,unit="native")),
angle_calc="along",force_flip=TRUE,
label_dodge=unit(3.0,"mm"),label_push=unit(-0.4,"mm")) +
## Width scale
scale_edge_width(range=c(0.2,4),breaks=c(1:10),name="Movements\nbetween zones") +
## Add arrows separately
geom_edge_link(arrow=ar,aes(start_cap=circle(node1.size,unit="native"),
end_cap=circle(node2.size,unit="native"))) +
## Nodes
geom_node_circle(aes(r=size)) +
## Plot location id
geom_node_label(aes(label=id),color="red",repel=TRUE,label.r=0.3,position="identity") +
## Plot work activity
geom_node_text(aes(size=w),label="w",color="green",position="identity") +
## Plot school activity
geom_node_text(aes(size=s),label="s",color="blue",position="identity") +
## Theme
theme_graph() + coord_fixed()
There are some fundamental issues:
Width of edges defined inweight
does not correspond to node ID (from/to
inedge
andname
innode
). For instance, weight3
is given to0->1
and1->0
in data frame but it appears between0<->2
in the graph,An edge between0<->1
gets inside of node0
even if margins are set bystart_cap
andend_cap
,Weight
labels besides edges are not centralized (it is located near from node 0)- Labels defined by
geom_node_label
overlaps nodes - Size of labels inside nodes (
w
ands
) seems okay, however they are not located asdodge
(they are overlapped each other)
Issues other than the first point are just aesthetic issues but the first point is fatal error of the plot. I plotted it in igraph
which gives appropriate relations between nodes and edges.
## Sample in igraph
E(net)$width <- E(net)$weight
plot(net,edge.width=E(net)$weight*5,vertex.size=V(net)$size*5,vertex.label.cex=3)
I highly appreciate your suggestions to solve any of above issues to obtain desired graph. I am new to use ggraph
and found some solutions to obtain current graph, however I have been stacking to fix above issues at this moment.
(I prefer to use ggraph
rather than igraph
to control its appearance precisely)
========== UPDATE ==========
Most of issues could be solved by the following scripts though it is very manual adjustment. One most important key is to remove loop edge between 0<->0
which caused inappropriate correspondence between label and actual width of edges.
## Load data frames as tbl_graph class
edge <- edge %>% mutate(from=from+1,to=to+1)
net <- tbl_graph(nodes=node,edges=edge,directed=TRUE)
## Set arrows
ar <- arrow(angle=30,length=unit(5,"mm"),ends="last",type="closed")
## Plot
ggraph(net,layout="graphopt") +
## Edges
geom_edge_link(aes(start_cap=circle(log(node1.size)+2,unit="native"),
end_cap=circle(log(node2.size)+2,unit="native"),
width=weight,label=weight),
position="identity",angle_calc="along",force_flip=TRUE,
label_dodge=unit(4.0,"mm"),label_push=unit(-0.4,"mm")) +
## Width scale
scale_edge_width(range=c(0.2,4),breaks=c(1:10),name="Movements\nbetween zones") +
## Add arrows separately
geom_edge_link(arrow=ar,aes(start_cap=circle(log(node1.size)+1,unit="native"),
end_cap=circle(log(node2.size)+1,unit="native"))) +
## Nodes
geom_node_circle(aes(r=log(size)+1)) +
## Plot location id
geom_node_label(aes(label=id,hjust=log(size+5),vjust=log(size+5)),repel=TRUE,
label.padding=unit(0.8,"mm"),label.r=unit(0.0,"mm"),label.size=0.1,size=3.5) +
## Plot work activity
geom_node_text(aes(size=w,hjust=log(w)+0.6),label="w",color="red",position="identity",vjust=0.4) +
## Plot school activity
geom_node_text(aes(size=s,hjust=-log(s)-0.3),label="s",color="blue",position="identity",vjust=0.4) +
## Size scale
scale_size(range=c(0,5),breaks=c(1:100),name="Numberof\nActivities",
guide=guide_legend(override.aes=list(rep("a",100)))) +
# scale_color() +
## Theme
theme_graph() + coord_fixed()
However there are two remaining issues on legend:
- How can I replace overlapped "w" and "s" by other font, such as "a" (activity)?
- How can I add one more manual legend "Types of activity" shown in desired result?
I posted it as a new question here