Skip to content
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

Possible to remove also the axes when frame=FALSE and grid=TRUE? #182

Closed
pglpm opened this issue Aug 2, 2024 · 15 comments
Closed

Possible to remove also the axes when frame=FALSE and grid=TRUE? #182

pglpm opened this issue Aug 2, 2024 · 15 comments

Comments

@pglpm
Copy link

pglpm commented Aug 2, 2024

Thank you for this fantastic lightweight plot function!

It's very close to something I wrote for my own use, so I'd be happy to switch to tinyplot, which is more carefully developed and maintained :)

I was wondering if there's an option to eliminate the thick axes bars completely when one has frame = FALSE and grid = TRUE, as in the enclosed screenshot.

If not, could this be added to the wishlist? :)

Screenshot_20240802_123941

@grantmcdermott
Copy link
Owner

grantmcdermott commented Aug 2, 2024

Thanks for the kind words @pglpm.

RE: your FR. It's definitely something I'd like to support (and have wanted to for a while). What we'd need to do is settle on a consistent argument interface. I think axes = FALSE needs to retain its current behaviour of removing all axes elements to ensure consistency with base plot. But perhaps we could support switching off the lines only with something like axes = NA?

P.S. A broader goal for the next release of tinyplot is to support theming elements. So a user could just call, say, tinytheme("minimal") and it would invoke this setting for all plots.

@zeileis
Copy link
Collaborator

zeileis commented Aug 2, 2024

If axes can take values other than TRUE and FALSE in tinyplot(), one could also go for something like axes = "ticks" (or another verbal description). This is easier to extend in case further types should be added in the future.

Instead of using axes one could also use xaxt and yaxt which are intended to be type specifications via character descriptions. The problem is just that de facto only "s" (standard) and "n" (none) are supported.

@grantmcdermott
Copy link
Owner

grantmcdermott commented Aug 2, 2024

Good points @zeileis. We actually don't support x(y)axt in tinyplot(), so that's something that should probably be fixed too.

So, is your thinking that we should support a "t" ("or "ticks") argument option for axes, xaxt and yaxt?

@zeileis
Copy link
Collaborator

zeileis commented Aug 3, 2024

My idea was to just go through axes and to come up with new descriptive names (such as "ticks") rather than just abbreviations (like "t"). The latter could be used by the end-users nevertheless due to match.arg().

However, compatibility with xaxt/yaxt might not be a bad idea. The catch is, though, that xaxt = "t" currently already works but has a different meaning. More precisely, the supported specifications are currently:

  • "s": standard (default)
  • "n": none
  • "l" and "t": accepted for compatibility with S but actually equivalent to "s"
  • everything else leads to an error with invalid value specified for graphical parameter ...

Given that compatibility with S is not important anymore, we could decide to give a different meaning to "l" and "t" if we want.

Last remark: While tinyplot(..., xaxt = "n") currently does not work, it is possibly to do (t)par(xaxt = "n") and then tinyplot(...).

@grantmcdermott
Copy link
Owner

Given that compatibility with S is not important anymore, we could decide to give a different meaning to "l" and "t" if we want.

How about:

"l" = "labels (only)"
"t" = "ticks + labels"

?

@zeileis
Copy link
Collaborator

zeileis commented Aug 3, 2024

And maybe also "a" for "axis" (+ labels)?

Internally, I would use something like:

axis_types <- c("standard", "none", "labels", "ticks", "axis")
if(is.character(axes)) {
  axes <- match.arg(axes, axis_types)
  xaxt <- axes
  yaxt <- axes
  axes <- axes != "none"
}
if (missing(xaxt)) xaxt <- substr(match.arg(xaxt, axis_types), 1L, 1L)
if (missing(yaxt)) yaxt <- substr(match.arg(yaxt, axis_types), 1L, 1L)

@grantmcdermott
Copy link
Owner

That looks great @zeileis. Do you want to put in a PR? Otherwise, I'll try to find some time over the weekend.

@pglpm
Copy link
Author

pglpm commented Aug 3, 2024

@grantmcdermott

P.S. A broader goal for the next release of tinyplot is to support theming elements. So a user could just call, say, tinytheme("minimal") and it would invoke this setting for all plots.

That will be fantastic!

Regarding which option to use for omitting the axes, I'm happy with any of the proposals I'm seeing :)

Thank you all!

@zeileis
Copy link
Collaborator

zeileis commented Aug 3, 2024

Do you want to put in a PR? Otherwise, I'll try to find some time over the weekend.

I can try. The missing part is, of course, how to actually support this in the Axis() calls because these xaxt/yaxt specifications are not supported there. My idea would be to play around with the Axis() calls in https://github.com/grantmcdermott/tinyplot/blob/main/R/tinyplot.R#L1079-L1102 to obtain the desired effects. Are there other places?

Also, currently the default is frame.plot = axes. How to we want to handle this? Make frame.plot also accept character? Or make the default frame.plot = NULL and then choose the default internally based on axes?

@grantmcdermott
Copy link
Owner

My idea would be to play around with the Axis() calls in https://github.com/grantmcdermott/tinyplot/blob/main/R/tinyplot.R#L1079-L1102 to obtain the desired effects. Are there other places?

No, I think that should be be the only place.

Also, currently the default is frame.plot = axes. How to we want to handle this? Make frame.plot also accept character? Or make the default frame.plot = NULL and then choose the default internally based on axes?

Ah, good catch. The latter option of frame.plot = NULL seems cleanest to me.

@zeileis
Copy link
Collaborator

zeileis commented Aug 3, 2024

OK, thanks. I have prepared PR #190 now. I've left the default of frame.plot = axes because frame.plot is long before the axes are handled. So it seemed to be best to add some extra handling of frame.plot early on in the function. And then it doesn't matter much whether I also handle character or not. But maybe you have a better idea for this. See also the somewhat unintuitive case in the PR description.

@zeileis
Copy link
Collaborator

zeileis commented Aug 4, 2024

PierGianLuca @pglpm with PR #190 merged, you can now do:

install.packages("tinyplot", repos = "https://grantmcdermott.R-universe.dev")
library("tinyplot")
x <- 0:100/10
y <- sin(x)
par(las = 1)
tinyplot(y ~ x, type = "l", col = "steelblue", axes = "labels", grid = TRUE)
tinyplot with new axes specification

I think this resolves the main issue that you raised.

I don't see an easy built-in way, though, to change the number of ticks on the x- and y-axis (like in your plot) and keeping the grid aligned with it. Maybe Grant @grantmcdermott has an idea for this.

@vincentarelbundock
Copy link
Collaborator

This is a very cool feature @zeileis well done!

@grantmcdermott
Copy link
Owner

I don't see an easy built-in way, though, to change the number of ticks on the x- and y-axis (like in your plot) and keeping the grid aligned with it. Maybe Grant @grantmcdermott has an idea for this.

I think the best way is just to fiddle with (t)par(lab), e.g.

library(tinyplot)

op = tpar(las = 1, lab = c(10,10,7))

x = 0:100/10
tinyplot(x, sin(x), type = "l", col = "steelblue", axes  ="labels", grid = grid(lty = "solid"))

tpar(op)

Created on 2024-08-03 with reprex v2.1.1

@zeileis
Copy link
Collaborator

zeileis commented Aug 4, 2024

Nice! Maybe put this example somewhere for reference?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants