plot rescales and normalizes graph even if it has vertex x and y attributes
What happens, and what did you expect instead?
I expect the graph drawing to be based on the x and y attributes of the vertices. The documentation for layout_nicely says
The current implementation works like this:
- If the graph has a graph attribute called ‘layout’, then this is used. If this attribute is an R function, then it is called, with the graph and any other extra arguments.
- Otherwise, if the graph has vertex attributes called ‘x’ and ‘y’, then these are used as coordinates. If the graph has an additional ‘z’ vertex attribute, that is also used.
When I force xlim and ylim to the range of those attributes, I get what I would expect by default, based on the documentation. There's a post in the forum where I asked about this, and the rescale = TRUE suggestion was made.
I think the issue is with the line of code where xlim = c(-1, 1) ylim = c(-1, 1) is imposed.
To reproduce
library(igraph)
n <- 11
a <- seq(0, 2 * pi, length.out = n + 1)[-1]
x <- 5 * cos(a)
y <- 3 * sin(a)
L <- matrix(c(x, y), ncol = 2)
G <- make_full_graph(n) |>
set_vertex_attr("x", value = x) |>
set_vertex_attr("y", value = y)
par(mfrow = c(1, 3))
plot(G, layout = layout_nicely(G), axes = TRUE)
plot(G, layout = L, rescale=FALSE, axes = TRUE)
plot(G, xlim = range(V(G)$x), ylim = range(V(G)$y),
rescale = FALSE, asp = 1, axes = TRUE)
Created on 2024-09-08 with [reprex v2.1.1](https://reprex.tidyverse.org/)
To be clear, the third panel is what I expect.
System information
I don't think any of this is relevant, but for completeness:
> version
platform aarch64-apple-darwin20
arch aarch64
os darwin20
system aarch64, darwin20
status
major 4
minor 3.3
year 2024
month 02
day 29
svn rev 86002
language R
version.string R version 4.3.3 (2024-02-29)
nickname Angel Food Cake
All packages updated today, and igraph at version 2.0.3
Thanks. I see, even without the asp argument:
options(conflicts.policy = list(warn = FALSE))
library(igraph)
n <- 11
a <- seq(0, 2 * pi, length.out = n + 1)[-1]
x <- 5 * cos(a)
y <- 3 * sin(a)
L <- matrix(c(x, y), ncol = 2)
G <- make_full_graph(n) |>
set_vertex_attr("x", value = x) |>
set_vertex_attr("y", value = y)
plot(G, layout = layout_nicely(G), axes = TRUE)

plot(G, layout = L, rescale = FALSE, axes = TRUE)

plot(G, xlim = range(V(G)$x), ylim = range(V(G)$y), rescale = FALSE, axes = TRUE)

Created on 2024-09-12 with reprex v2.1.0
I'm confused why the first two plots keep the aspect ratio, but the third plot doesn't. I agree that we could do xlim = NULL, ylim = NULL in the formals and use c(-1, 1) for rescale = FALSE and whatever is the best default for rescale = TRUE .
Tidyverse design guide re NULL defaults: https://design.tidyverse.org/defaults-short-and-sweet.html#null-default
I am in the habit when plotting geographical data (which is eventually the aim here) to include asp = 1 in plot options as usually you want geographic coordinates to be treated as equal in the two dimensions, which is why it is in my code example. Perhaps plot.igraph defaulting to asp = 1 has something to do with this line in the plot.R code:
asp <- params("plot", "asp")
but that's way too deep in the weeds of how igraph handles parameters and their defaults for me to have any certainty about that suggestion. But, e.g., I get
> igraph:::i.parse.plot.params(G, list())("plot", "asp")
[1] 1
which suggests that the plot function is setting asp to a default value of 1.
But really someone who knows how these internal workings of igraphwork (which might be you @krlmlr!) and especially understands how they are intended to work should comment.
In any case, there's a whole chunk of the code (starting at line 100) which is similar in format to above.
To be clear, I am totally guessing here. I only happened on the igraph:::i.etc. line above via this fairly random code snippet so I am way above my pay grade and outside my comfort zone here.
cc @maelle I take this on if thats ok. I feel like I understand the plotting code well enough for this
Yes that is more than ok. 🙏