-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dedicated draw_legend function #76
Conversation
@zeileis Do you mind reviewing this one for me? |
Sorry to nag @zeileis, but do you think you’ll have time to look at this? I don’t mean to rush you (no obligations on your side!). But I’m hoping to push out the next plot2 release sooner rather than later, and would like to get this internal change sorted before adding one or two more features. If you don’t have time—again, no pressure—then I’ll probably merge as-is, since it doesn’t affect any user-facing syntax. |
Apologies for being so slow (again). I had taken a quick look and did not really understand exactly how I would specifically be interested in how the function might facilitate (or not) faceting and the |
Small side note because I saw I wasn't aware of this inefficiency of |
Thanks @zeileis. Apologies for not making the use-cases clearer. But, yes, my primary goal in moving it to a stand-alone function is make it easy re-use in situations like those required by I don't intend for I'm typing this all on my phone, but will carve out some time during the week to provide some clearer examples. Thanks too for the namespace tip: TIL! |
Thanks for the explanations, Grant @grantmcdermott ! Bubble charts are a good motivation for this. I look forward to some examples - but no pressure from me :-) |
I'm not sure how compelling this example will be as a manual implementation. But here is the sort of functionality that I envisage having a separate draw_legend function will enable. devtools::load_all("~/Documents/Projects/plot2/")
#> ℹ Loading plot2
# utilty rescaling function for bubble plot legend
rscl = function (x) {
if (length(x) > 5) {
x = pretty(x, n = 5)
} else {
x = sort(x)
}
x = x[x > 0]
from = range(x)
to = c(1, 2.5)
out = (x - from[1])/diff(from) * diff(to) + to[1]
names(out) = x
return(out)
}
# main plot
plot2(
Sepal.Length ~ Petal.Length | Species, iris,
cex = rscl(iris$Petal.Width),
grid = TRUE, legend = "topright!"
)
# now add the size legend
l = rscl(iris$Petal.Width)
draw_legend(
"bottomright!",
legend.args = list(),
by_dep = "Petal.Width",
lgnd_labs = names(l),
cex = l,
type = "p",
pch = 1,
col = "black",
new_plot = FALSE
) Created on 2023-10-10 with reprex v2.0.2 Obviously, we need to figure out positioning/alignment of two legends... and any dedicated But IMO those tweaks can come down the line when they are implemented for the different chart types. So having draw_legend as a separate function doesn't create any downside in the interim, at least. And I think it will make it easier to compose multiple legends internally once we reach that point. |
Another example, this time for faceted plots. I'll certainly grant that this manual implementation is pretty clunky. But I think it shows a path towards how we could actually implement facets internally... partly by using a dedicated devtools::load_all("~/Documents/Projects/plot2/")
#> ℹ Loading plot2
data("penguins", package = "palmerpenguins")
par(pch = 19)
# Draw (empty) new plot with legend first
draw_legend(
"bottom!",
legend.args = list(),
by_dep = "sex",
lgnd_labs = levels(penguins$sex),
type = "p",
pch = 19,
cex = 1,
col = palette()[1:2]
)
# Now set the facets
par(mfrow = c(1, 3))
# See: https://github.com/grantmcdermott/plot2/issues/65
par(mfg = c(1, 1))
# Finally, draw the individual plots.
## This next chunk is just a manual mock up of stuff that we would handle
## internally within plot2
penguins_split = split(penguins, penguins$species)
invisible(lapply(
seq_along(penguins_split),
\(i) plot2(
body_mass_g ~ flipper_length_mm | sex, penguins_split[[i]],
frame = FALSE, grid = TRUE,
legend = FALSE,
main = names(penguins_split)[[i]],
xlim = range(penguins$flipper_length_mm, na.rm = TRUE),
ylim = range(penguins$body_mass_g, na.rm = TRUE)
)
)) Created on 2023-10-10 with reprex v2.0.2 |
I'm going to go ahead and merge this, since I plan to dedicate some dev time over the next few days for additional features that build on this change. Hope that's okay! |
OK, thanks. I didn't have time until today due to heavy teaching on Tue/Wed/Thu. Thanks also for the facets example, very useful. Do you also have thoughts on how to modify the |
Not fully within the plot2 framework yet. I do have another mock-up here that tries to do some more sophisticated plotting of the axes and facet titles to avoid duplication. But even this example leaves some awkward spacing between the individual plots. One open question is whether to go through |
So far when I implemented things like this I used I haven't worked much with What might be an advantage - I haven't tried - is that layout() should be flexible enough to set up suitable panels for legend, annotation, etc. Have you ever tried to play around with this? |
This PR breaks the legend drawing component into a separate, dedicated function:
draw_legend()
.In addition to simplifying the main
plot2()
code, it has the virtue that it should enable dual legends down the road (e.g. for "bubble" charts as per discussion in #50).I also fixed some minor issues with the old legend creation process (mostly related to suboptimal plot margins), which is why we have a few updated snapshots too.