Closed grantmcdermott closed 1 year ago
That all sounds good to me. This is the perfect time for breaking changes.
+1
Talking about breaking changes: Is everyone still happy with the name plot2()
? I think it's not a great name but I'm not sure whether I have anything better. I just thought I would mention my doubts now rather than after a CRAN release.
A somewhat longer but more verbose alternative might be baseplot()
. Short alternatives would be draw()
or viz()
. Maybe someone else has better ideas. Currently, I think I slightly prefer baseplot()
over plot2()
.
Happy to make this a separate issue if you think it is worthwhile to discuss.
Happy to make this a separate issue if you think it is worthwhile to discuss.
Bedtime here, but yes please role into a separate issue and we can discuss.
Another thing to think about while we're at it: Should the default palette for small groups still be Okabe-Ito? I think it's an elegant palette, but I'm a bit worried the yellow (fifth group) is hard to see with standard par
settings (esp. the pure white plot background). We might think of defaulting to the regular R (>=4.0) palette()
instead?
I like the idea of being as close to base as possible, while allowing easy switch. So the 4.0.0 base palette feels like a nice choice.
One palette I've been using recently is Tol's: https://cran.r-project.org/web/packages/khroma/vignettes/tol.html
I agree, consistency with base R would be a nice touch and now it's so easy to switch.
Just for the record: I've had a similar discussion with Deepayan (Sarkar) recently and he was nice enough to incorporate the outcome of our discussions into the most recent lattice version (0.21-8). It now uses the following defaults:
symbol = palette.colors(palette = "Okabe-Ito")[c(6, 2, 4, 7, 3, 5, 8)]
fill = NULL
symbol
colors as fill
colors. Lightening is done in HCL space using only grDevices
. This is not quite as good as colorspace::lighten()
but has the advantage that no additional dependencies are introduced.region = hcl.colors(14, palette = "YlGnBu", rev = TRUE)
I think that none of this is directly relevant for plot2
at the moment. But maybe it becomes useful at some point.
Super helpful, thanks for the feedback both.
I'll priortise this as the next PR and then I think we should release the next (dev) version, given the breaking change. Will obviously have to update all of the snapshots in our test suite too.
PS. @zeileis Thanks for the HU on lattice. That's cool! Like lattice (trellis.par.set
) and ggplot2 (e.g., getOption("ggplot2.discrete.fill")
) I'd ultimately like to allow users to control plot2 default palettes via a global option. I'll see if I can work that in...
TL;DR Roll the
legend.position
andlegend.args
arguments into a singlelegend = legend(...) / legend = <keyword>
argument. Similarly, roll thepalette
andpalette.args
arguments into a singlepalette = <function> / palette = <keyword>
argument.Problem
An API/design decision I'd like to nail down before a CRAN submission is the best way to handle the
legend
andpalette
arguments. At the moment, each of these is broken into two user-facing arguments. Respectively:legend.position
(accepts a keyword string like "right!" or "topleft") andlegend.args
(accepts a list of arguments, passed down tolegend()
)palette
(accepts a string for like "Viridis" that matches at least one output frompalette.pals()
orhcl.pals()
) andpalette.args
(accepts a list of arguments, passed down topalette.colors()
orhcl.colors()
).The current setup has some advantages, but I don't really like that we require two separate arguments for each "aspect". Other concerns include the fact that we don't use all arguments available to, say, legend creation and existing arguments don't necessarily align with their base equivalents. (An example: the "title" argument in
legend.args
is equivalent to the "legend" argument in the baselegend()
function.) Finally, the current API also places some constraints on user-specified inputs. For example, if a user wanted to supply a bespoke colour-generating palette as a function.Proposal
An alternative would be to roll each of these into a single argument that accepts a function (and possibly a string for a convenient shorthand to change a leading/key feature). Specifically:
legend = legend(bty = "o", legend = "my legend title")
, where we splice in any remaining defaults. We could also catch/allow users to pass a key position string as an alternative convenience option, e.g. "bottom!". (One slight concern/inconsistency is whether the keyword behaviour should be reserved for position, as I've suggested here, or whether it should be the legend title...)palette()
, orpalette.cols()
,hcl.colors()
. The trick here is that the leading "n" argument would usually (always?) be redundant, since we calculate n internally based on the number of groups inby
. Similar to the current behaviour, we could catch/allow users to pass down a known palette string as a convenience option e.g., "Tableau 10".Decision?
Personally I'm leaning towards the proposed setup, despite be a breaking change. I would love to hear other opinions before putting in a PR, though.