| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
ggplot2's Guides$merge() breaks ties between same-order guides using a content hash (rlang::hash()), which has no relation to aesthetic declaration order. A recent rlang release changed that hash, flipping the tie-break and silently reordering combined legend titles (e.g. "factor(vs)<br />factor(cyl)" became "factor(cyl)<br />factor(vs)"). Legend entries themselves are named independently, always in aesthetic declaration order (layers2traces.R's discreteScales), so title order and entry order could now disagree. Reorder guides in get_gdefs_ggproto() by (explicit guide order, aesthetic declaration order) so the title always agrees with the entries it labels, regardless of upstream hashing changes.
Silences the R CMD check NOTE about deprecated special names in structure() calls.
| Back | FazBrowse Home | New Git URL |
Why
CRAN and CI started failing on test-ggplot-legend.R with no code changes on our side:
Root cause: when a plot has two separate discrete legends (e.g. color +
shape) that ggplot2 can't merge into one, ggplot2 orders them for display
using a content hash (rlang::hash()) as a tie-break whenever neither guide
has an explicit order=. A recent rlang release changed how that hash is
computed ("all hash values will now be different" - rlang 1.3.0 NEWS), which
silently flipped which guide sorts first - in real ggplot2::ggplotGrob()
renders too, not just plotly's output. Nothing in this package or in user
plot code changed; a transitive dependency bump reordered something ggplot2
never actually guaranteed the order of.
That would just be cosmetic, except plotly builds the combined legend title
(R/ggplotly.R) from that same hash-ordered guide list, while the legend
entries underneath it (the actual traces/markers) are named independently,
always in the order aesthetics were declared in aes()
(layers2traces.R's discreteScales). So the rlang bump made the title
order and the entry order disagree with each other, which is the actual bug
worth fixing here (not just "match whatever ggplot2 happens to do this
week").
What changed
get_gdefs_ggproto() now re-sorts guides after guides$merge() by
(explicit guide order, aesthetic declaration order) instead of leaving
ggplot2's hash tie-break in place. This:
regardless of future hashing/rlang/ggplot2 changes
one (see the "legend can be manipulated via guides()" test, which
deliberately declares shape before color in aes() but orders them the
opposite way via order=)
Known gap (not fixed here, on purpose): the pre-ggplot2-3.5.0 legacy guide
code path (get_gdefs()) has the identical latent ordering issue, but it's
untestable in any currently-installed ggplot2 and effectively dead code, so
it was left alone.
Follow-up needed: tests/testthat/_snaps/ggplot-legend/scatter-legend.svg
still encodes the old (regressed) title order and needs to be regenerated
via the visual-test Docker flow before the macOS/VISUAL_TESTS CI leg will
pass again.