I would like to move the position of the edge label so that it is not on top of it. Here is a little example:
g <- graph.empty(n=3)
g <- graph(c(1,2,3,2,1,3), directed=T)
E(g)$weight <- c(3,2,5)
plot(g, edge.label = E(g)$weight)
In my example, the labels are on the edges and I want them to move perpendicular to the edge a little bit.
Sorry to be the guy that says "How about using library(x)?"
My code using ggraph?
library(igraph)
library(ggraph)
g <- graph.empty(n=3)
g <- graph(c(1,2,3,2,1,3), directed=T)
E(g)$weight <- c(3,2,5)
#your plot
plot(g, edge.label = E(g)$weight)
#using ggraph
ggraph(graph = g) +
geom_node_circle(size = 1, mapping = aes(r =0.03), fill="goldenrod") +
geom_edge_link(mapping = aes (label = weight),
arrow = arrow(type = "closed", angle = 15),
end_cap = circle(8, 'mm'), ,
start_cap = circle(8, 'mm'),
colour="grey",
label_dodge = unit(5, "mm"),
angle_calc = "along") +
geom_node_text(mapping = aes(label = "2")) +
theme_graph()
igraph plotting has parameters edge.label.x
and edge.label.y
for placing the edge labels, but these must be specified in the coordinates used for making the plot. To get the right coordinates, you need to take control of the layout yourself. @GaborCsardi suggested something like this in his comment, but implementing this is complicated enough that I think it deserves a full answer.
## Setup - your example graph
library(igraph)
g <- graph.empty(n=3)
g <- graph(c(1,2,3,2,1,3), directed=T)
E(g)$weight <- c(3,2,5)
Now, instead of just plotting, we capture the layout of the vertices so that we can use it. I set the random seed for reproducibility.
set.seed(1234)
LO = layout_nicely(g)
The layout gives x-y coordinates for the vertices that we can use for plotting. We want to use those positions to compute where we will write the edge labels. We will start by just computing the centers of the edges and then adjusting the positions perpendicular to the edges. One fine point: if an edge is nearly horizontal, the slope of the perpendicular is nearly infinite, so the calculation of the perpendicular displacement may cause problems. We will test for this and sidestep that problem.
## Start with the centers of the edges (on line)
ELx = rep(0, ecount(g))
ELy = rep(0, ecount(g))
for(i in 1:ecount(g)) {
ELx[i] = (LO[ends(g,i)[1],1] + LO[ends(g,i)[2],1])/2
ELy[i] = (LO[ends(g,i)[1],2] + LO[ends(g,i)[2],2])/2 }
## Adjust perpendicular to line
d = 0.03
for(i in 1:ecount(g)) {
if(abs(LO[ends(g,i)[1],2] - LO[ends(g,i)[2],2]) < 0.1) {
## This avoids problems with horizontal edges
ELy[i] = ELy[i] + shift
} else {
S = (LO[ends(g,i)[2],1] - LO[ends(g,i)[1],1]) /
(LO[ends(g,i)[1],2] - LO[ends(g,i)[2],2])
shift = d / sqrt(1 + S^2)
ELx[i] = ELx[i] + shift
ELy[i] = ELy[i] + S*shift
}
}
Now we can plot and specify a better position for the edge labels. By default, plotting of igraph objects rescales the layout to the range [-1,1] for both the x and y axes. If that happens, the values in the layout no longer correspond to positions on the graph. So we will use rescale=FALSE
. But igraph still wants to plot in the range [-1,1], so we also have to set xlim and ylim.
plot(g, layout=LO, edge.label = E(g)$weight,
rescale=FALSE, xlim=range(LO[,1]), ylim=range(LO[,2]),
edge.label.x=ELx, edge.label.y=ELy)
The adjustment distance d = 0.03
is somewhat arbitrary. I picked it to make this graph look nice. If you have a more complicated graph, you might want to adjust that distance.
You can move the edge labels vertically by adding return characters. You can move them horizontally by adding spaces. For example,
plot(g, edge.label = c(" 3","2\n","5\n"))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With