Skip to content

Commit 9970b12

Browse files
cpsievertclaude
andcommitted
Fix #2467: multi-aesthetic scales now show legend and split traces correctly
When a scale has multiple aesthetics (e.g., aesthetics = c("colour", "fill")), the discreteScales registry now stores each aesthetic separately instead of combining them with "_". This ensures that "colour_plotlyDomain" matches discreteScales[["colour"]] for proper trace splitting and legend generation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fcea644 commit 9970b12

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

R/layers2traces.R

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ layers2traces <- function(data, prestats_data, layout, p) {
7878
}, data, hoverTextAes)
7979

8080
# draw legends only for discrete scales
81+
# Register each aesthetic separately for proper legend matching (fixes #2467)
82+
# When a scale has multiple aesthetics (e.g., c("colour", "fill")), we need
83+
# individual entries so "colour_plotlyDomain" matches discreteScales[["colour"]]
8184
discreteScales <- list()
8285
for (sc in p$scales$non_position_scales()$scales) {
8386
if (sc$is_discrete()) {
84-
nm <- paste(sc$aesthetics, collapse = "_")
85-
discreteScales[[nm]] <- sc
87+
for (aes_name in sc$aesthetics) {
88+
discreteScales[[aes_name]] <- sc
89+
}
8690
}
8791
}
8892
# Convert "high-level" geoms to their "low-level" counterpart

tests/testthat/test-ggplot-color.R

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,25 @@ test_that("scale_*_manual with unused aesthetics does not error (#2466)", {
1717
aesthetics = c("colour", "fill")
1818
)
1919
# Should not error with "undefined columns selected"
20-
# (Note: trace splitting with multi-aesthetic scales is a separate issue #2467)
2120
expect_error(plotly_build(ggplotly(p)), NA)
2221
})
2322

23+
test_that("multi-aesthetic scales show legend and split traces correctly (#2467)", {
24+
# When scale has aesthetics = c('colour', 'fill') and both are used,
25+
# traces should be split by the variable and legend should appear
26+
p <- ggplot(iris, aes(Sepal.Length, Sepal.Width, colour = Species, fill = Species)) +
27+
geom_point(shape = 21) +
28+
scale_colour_manual(
29+
values = c("setosa" = "red", "versicolor" = "blue", "virginica" = "green"),
30+
aesthetics = c("colour", "fill")
31+
)
32+
L <- plotly_build(ggplotly(p))$x
33+
# Should have 3 traces (one per Species level)
34+
expect_equal(length(L$data), 3)
35+
# Should show legend
36+
expect_true(any(sapply(L$data, function(d) isTRUE(d$showlegend))))
37+
# Trace names should be the species names
38+
trace_names <- sapply(L$data, function(d) d$name)
39+
expect_true(all(c("setosa", "versicolor", "virginica") %in% trace_names))
40+
})
41+

0 commit comments

Comments
 (0)