grantmcdermott / tinyplot

Lightweight extension of the base R graphics system
https://grantmcdermott.com/tinyplot
Apache License 2.0
226 stars 7 forks source link

Dates should work properly #77

Closed grantmcdermott closed 1 year ago

grantmcdermott commented 1 year ago
dat = data.frame(
    y = rnorm(24),
    ds = seq(as.Date("2021-01-01"), as.Date("2022-12-01"), by = "month")
)

plot(y ~ ds, dat)


library(plot2)
plot2(y ~ ds, dat)

Created on 2023-09-06 with reprex v2.0.2

vincentarelbundock commented 1 year ago

Looks fantastic!

On Wed, Sep 6, 2023, at 19:51, Grant McDermott wrote:

dat = data.frame( y = rnorm(24), ds = seq(as.Date("2021-01-01"), as.Date("2022-12-01"), by = "month") )

plot(y ~ ds, dat)

https://camo.githubusercontent.com/0a4905a5dbe59b53dc7e6568888304deed5177a30c54f601e9fb790ee888b0d0/68747470733a2f2f692e696d6775722e636f6d2f567951665941632e706e67

library(plot2) plot2(y ~ ds, dat)

https://camo.githubusercontent.com/9e9db277e610928779c5bfb762f1318b5b178f03521a7c54e3a0ef915bd2583a/68747470733a2f2f692e696d6775722e636f6d2f7a5855767357722e706e67

Created on 2023-09-06 with reprex v2.0.2 https://reprex.tidyverse.org/

— Reply to this email directly, view it on GitHub https://github.com/grantmcdermott/plot2/issues/77, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHQ7MMLGRRFQRYSJOAIZ6TXZED7XANCNFSM6AAAAAA4OCADQQ. You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Vincent Arel-Bundock

Professeur agrégé / Associate professor Université de Montréal, Science politique http://arelbundock.com

Livre en libre accès: Analyse Causale et Méthodes Quantitatives http://arelbundock.com/acmq.html

zeileis commented 1 year ago

I haven't fully tested this but I suspect that the axis() calls have to be replaced by Axis() calls. For example, axis(1) should become Axis(x, side = 1) etc.

That means instead of https://github.com/grantmcdermott/plot2/blob/main/R/plot2.R#L658-L665 it's probably:

    if (isTRUE(axes)) {
      if (type %in% c("pointrange", "errorbar", "ribbon") && !is.null(xlabs)) {
        Axis(x, side = 1, at = xlabs, labels = names(xlabs))
      } else {
        Axis(x, side = 1)
      }
      Axis(y, side = 2)
    }

With this change the simple example you posted at the beginning of this issue works. But I haven't tested all the other possible types plot2() supports.

grantmcdermott commented 1 year ago

Thanks for the tip @zeileis. I use your suggestion and added a few extra changes to make sure that the grid alignment works nicely for date-time objects (incl. POSIX, strptime etc).

dat = data.frame(
  y = rnorm(24),
  ds = seq(as.Date("2021-01-01"), as.Date("2022-12-01"), by = "month")
)

library(plot2)
plot2(y ~ ds, dat, grid = TRUE)

Created on 2023-09-06 with reprex v2.0.2

zeileis commented 1 year ago

Thanks, Grant, the grid looks great. However, I dislike the hard-coded special type of grid for the base R date/time classes. It's not a big issue, though, because it is reasonably straightforward to draw a custom grid afterwards.

The nice thing about Axis() is that it is object-oriented and data classes can bring their own methods. For example, yearmon/yearqtr from zoo do so. But I think there's no analogous method for determining the locations for the grid. Hence I like your trick via pretty(extendrange()) because pretty() is again generic. Maybe it would be better to always use this and not just for Date/POSIXt?

grantmcdermott commented 1 year ago

Hence I like your trick via pretty(extendrange()) because pretty() is again generic. Maybe it would be better to always use this and not just for Date/POSIXt?

Definitely worth thinking about, esp if grid is essentially doing the same thing under the hood (without full generic dispatch). Feel free to propose that in a small PR when you get a sec.

zeileis commented 1 year ago

OK, done now.