matplot.Date & matplot.POSIXct

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

matplot.Date & matplot.POSIXct

Spencer Graves-3

Hello, All:


       Roughly a decade ago, I added "matplot.Date" and
"matplot.POSIXct" to the "fda" package, so we could get reasonable
labeling of the horizontal axis when "x" was class "Date" or "POSIXct". 
I also added a local version of "matplot.default" that just changes the
defaults for "xlab" and "ylab".


       Would anyone care to comment on this?


       In particular, might there be any interest among the R Core Team
of adding "matplot.Date" and "matplot.POSIXct" to the "graphics" package?


       Secondarily, might anyone have any thoughts about the defaults
for "xlab" and "ylab" in "graphics::matplot"?


       I ask, because the Jim Ramsay, Giles Hooker and I are preparing a
new release of "fda", and Jim asked me if we needed to to have "matplot"
masking "graphics::matplot".  Rather than answer that question, I
thought I would ask a larger question of this group.


       Thanks,
       Spencer Graves

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Abby Spurdle
Maybe I'm missing something really obvious here, but I was unable to
create a matrix out of POSIXct object(s).
Perhaps that deserves a separate discussion...?

Regarding your other comments/questions:
(1) You should *NOT* mask functions from the graphics package (or
base, stats, etc), except possibly for personal use.
(2) The xlab and ylab are fine.


B.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Spencer Graves-3
       Thanks for the reply.


On 2020-01-27 19:56, Abby Spurdle wrote:
> Maybe I'm missing something really obvious here, but I was unable to
> create a matrix out of POSIXct object(s).
> Perhaps that deserves a separate discussion...?


       Can you provide an example?


       The standard matplot application that concerns me is with
matplot(x, y, ...) where x has class Date or POSIXct and y is a matrix. 
The "fda" package on CRAN includes a "matplot" help page with examples
that worked when I tested them recently.


       If you have an example that you think should work but doesn't I'd
like to know.  Maybe it should be added to the examples in
fda::matplot.Rd file, then the code should be modified until it works.
>
> Regarding your other comments/questions:
> (1) You should *NOT* mask functions from the graphics package (or
> base, stats, etc), except possibly for personal use.
> (2) The xlab and ylab are fine.


       In most situations, I agree with your comment that, "You should
*NOT* mask functions from the graphics package (or base, stats, etc)".


       However, when the behavior of the function in graphics, base, or
stats seems patently inappropriate and not adequately considered, then I
think that someone should mask the function in the core distribution
with one whose behavior seems more consistent with what most users would
most likely want.


       Ten or twelve years ago, I concluded that the behavior of
graphics::matplot(x, y, ...) was inappropriate when x is either of class
Date or POSIXct.  Specifically, it labeled the horizontal axis the same
as graphics::matplot(as.numeric(x), y, ...).  I think it should instead
be labeled the same as graphics::plot(x, y[,1], ...) in such cases.  To
fix this problem, I made fda::matplot generic; graphics::matplot is not
generic.  And a coded methods for x of class numeric, matrix, Date and
POSIXct plus a default.  Each calls either graphics::matplot or matlines
as appropriate after first setting up the horizontal axis properly if x
is of class Date or POSIXct.


       For specific examples, consider the following taken from
fda::matplot.Rd:


invasion1 <- as.Date('1775-09-04')
invasion2 <- as.Date('1812-07-12')
earlyUS.Canada <- c(invasion1, invasion2)
Y <- matrix(1:4, 2, 2)
graphics::matplot(earlyUS.Canada, Y)
# horizontal axis labeled per as.numeric(earlyUS.Canada),
# NOT as Dates
fda::matplot(earlyUS.Canada, Y)
# problem fixed.


# POSIXct
AmRev.ct <- as.POSIXct1970(c('1776-07-04', '1789-04-30'))
graphics::matplot(AmRev.ct, Y)
# horizontal axis labeled per as.numeric(AmRev.ct),
# NOT as POSIXct
fda::matplot(AmRev.ct, Y)
# problem fixed.


       Comments?
       Thanks again for the reply.
       Spencer Graves
>
> B.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Abby Spurdle
> > Maybe I'm missing something really obvious here, but I was unable to
> > create a matrix out of POSIXct object(s).
> > Perhaps that deserves a separate discussion...?
>    Can you provide an example?

------
#date and time objects
x = Sys.Date () + 1:16
y = as.POSIXct (x)

#matrices
str (matrix (x, 4, 4) )
str (matrix (y, 4, 4) )
------

Creating a matrix from a Date or POSIXct object, results in a numeric
matrix, not a date/time matrix.

I think that date/time matrices could be useful.
It's possible that this has been discussed before.
But if not, it may be good to discuss it.

And returning to your original post...

I re-read the documentation for the matplot function.
And I feel that it's ambiguous.

The description says:
"Plot the columns of one matrix against the columns of another."
i.e. The matplot function is for *matrices*.

However, then it says:
"x,y vectors or matrices of data for plotting. The number of rows should match."

I'm guessing the current intention is that standard vectors (without a
dim attribute) would be coerce-ible to single-column matrices,
implying that using this function with date and time objects, is
contrary to the way it's currently designed to work.

But...

After reading your examples and re-reading the documentation, your
main suggestion that matplot should support Date and POSIXct objects,
is still *probably* a good one. I note that function is not generic,
and modifications to it would not necessarily be trivial.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Edzer Pebesma
Whether something "is" a matrix depends on whether you listen to
is.matrix(x) or to inherits(x, "matrix"):

x = Sys.Date () + 1:16
y = as.POSIXct (x)
dim(y) = c(4,4)
is.matrix(y)
# [1] TRUE
inherits(y, "matrix")
# [1] FALSE

f = factor(letters[1:9])
dim(f) = c(3,3)
is.matrix(f)
# [1] TRUE
inherits(f, "matrix")
# [1] FALSE

I'm using (abusing?) this in the stars package, where it is convenient
to have n-D arrays of type factor, Date or POSIXct, mostly because the [
method works:

(f2 <- f[1:2,1:2])
#      [,1] [,2]
# [1,] a    d
# [2,] b    e
# Levels: a b c d e f g h i
is.matrix(f2)
# [1] TRUE


On 1/28/20 9:09 AM, Abby Spurdle wrote:

>>> Maybe I'm missing something really obvious here, but I was unable to
>>> create a matrix out of POSIXct object(s).
>>> Perhaps that deserves a separate discussion...?
>>    Can you provide an example?
>
> ------
> #date and time objects
> x = Sys.Date () + 1:16
> y = as.POSIXct (x)
>
> #matrices
> str (matrix (x, 4, 4) )
> str (matrix (y, 4, 4) )
> ------
>
> Creating a matrix from a Date or POSIXct object, results in a numeric
> matrix, not a date/time matrix.
>
> I think that date/time matrices could be useful.
> It's possible that this has been discussed before.
> But if not, it may be good to discuss it.
>
> And returning to your original post...
>
> I re-read the documentation for the matplot function.
> And I feel that it's ambiguous.
>
> The description says:
> "Plot the columns of one matrix against the columns of another."
> i.e. The matplot function is for *matrices*.
>
> However, then it says:
> "x,y vectors or matrices of data for plotting. The number of rows should match."
>
> I'm guessing the current intention is that standard vectors (without a
> dim attribute) would be coerce-ible to single-column matrices,
> implying that using this function with date and time objects, is
> contrary to the way it's currently designed to work.
>
> But...
>
> After reading your examples and re-reading the documentation, your
> main suggestion that matplot should support Date and POSIXct objects,
> is still *probably* a good one. I note that function is not generic,
> and modifications to it would not necessarily be trivial.
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

--
Edzer Pebesma
Institute for Geoinformatics
Heisenbergstrasse 2, 48151 Muenster, Germany
Phone: +49 251 8333081
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Martin Maechler
In reply to this post by Spencer Graves-3
>>>>> Spencer Graves
>>>>>     on Mon, 27 Jan 2020 23:02:28 -0600 writes:

    >       Thanks for the reply.
    > On 2020-01-27 19:56, Abby Spurdle wrote:
    >> Maybe I'm missing something really obvious here, but I was unable to
    >> create a matrix out of POSIXct object(s).
    >> Perhaps that deserves a separate discussion...?

yes, very much a separate discussion.
Let's come back to Spencer's topic of matplot() :

    [....]

    >       The standard matplot application that concerns me is with
    > matplot(x, y, ...) where x has class Date or POSIXct and y is a matrix. 

    > The "fda" package on CRAN includes a "matplot" help page with examples
    > that worked when I tested them recently.

Indeed.  That's how I understood you well.
matplot() has been one of my favorite plotting functions in S
and Splus in the 1990s ... and that's why the R source code of
matplot(), matpoints(), and matlines()  still has a comment
mentioning that I wrote (the first version of) it for R on June 27, 1997.

By design (from S), matplot() {etc} has always been thought as a convenience
wrapper to calling
        plot() and lines(),  lines(),  lines()
or     plot() and points(), points(), points()

{plot() : for setting up coord.system, draw axes, titles, ...},
-- notably also for adhering to the DRY (instead of WET)
   programming principle (-> "Don't Repeat Yourself")  --

*and* -- be assured -- more than 99% of its use has been for the
special case where x has been a numeric vector and y a matrix
with several columns and indeed, the following part from the
beginning of  matplot()'s source code has basically already been in the
version from 1997 and is all about having it work for
vectors treated as 1-column matrices :

------------------------------------------------------------------------

    if(missing(x)) {
        if(missing(y)) stop("must specify at least one of 'x' and 'y'")
        else x <- seq_len(NROW(y))
    } else if(missing(y)) {
        y <- x; ylabel <- xlabel
        x <- seq_len(NROW(y)); xlabel <- ""
    }
    kx <- ncol(x <- as.matrix(x))
    ky <- ncol(y <- as.matrix(y))
    n <- nrow(x)
    if(n != nrow(y)) stop("'x' and 'y' must have same number of rows")

    if(kx > 1L && ky > 1L && kx != ky)
        stop("'x' and 'y' must have only 1 or the same number of columns")
    if(kx == 1L) x <- matrix(x, nrow = n, ncol = ky)
    if(ky == 1L) y <- matrix(y, nrow = n, ncol = kx)
    k <- max(kx, ky) ## k == kx == ky

------------------------------------------------------------------------





    >       If you have an example that you think should work but doesn't I'd
    > like to know.  Maybe it should be added to the examples in
    > fda::matplot.Rd file, then the code should be modified until it works.
    >>
    >> Regarding your other comments/questions:
    >> (1) You should *NOT* mask functions from the graphics package (or
    >> base, stats, etc), except possibly for personal use.
    >> (2) The xlab and ylab are fine.


    >       In most situations, I agree with your comment that, "You should
    > *NOT* mask functions from the graphics package (or base, stats, etc)".


    >       However, when the behavior of the function in graphics, base, or
    > stats seems patently inappropriate and not adequately considered, then I
    > think that someone should mask the function in the core distribution
    > with one whose behavior seems more consistent with what most users would
    > most likely want.


    >       Ten or twelve years ago, I concluded that the behavior of
    > graphics::matplot(x, y, ...) was inappropriate when x is either of class
    > Date or POSIXct.  Specifically, it labeled the horizontal axis the same
    > as graphics::matplot(as.numeric(x), y, ...).  I think it should instead
    > be labeled the same as graphics::plot(x, y[,1], ...) in such cases.  To
    > fix this problem, I made fda::matplot generic; graphics::matplot is not
    > generic.  And a coded methods for x of class numeric, matrix, Date and
    > POSIXct plus a default.  Each calls either graphics::matplot or matlines
    > as appropriate after first setting up the horizontal axis properly if x
    > is of class Date or POSIXct.

I pretty much agree with your judgement here, Spencer.
What you say (and I assume your fda::matplot() does) is still
implementing the original basic idea of being a convenience
wrapper for a call to plot() and typically several calls
to lines() or points()...

and indeed in R {graphics}, plot(), lines() and points()
all have been S3 generics for a long time and so it seems
naturaly that a wrapper to these functions should also dispatch
correctly ...

possibly *not* by becoming S3 generic itself, but just, conceptually,
by ensuring *not* to change the S3 class of 'x' before calling
plot(), points() and lines() ....


    >       For specific examples, consider the following taken from
    > fda::matplot.Rd:


    > invasion1 <- as.Date('1775-09-04')
    > invasion2 <- as.Date('1812-07-12')
    > earlyUS.Canada <- c(invasion1, invasion2)
    > Y <- matrix(1:4, 2, 2)
    > graphics::matplot(earlyUS.Canada, Y)
    > # horizontal axis labeled per as.numeric(earlyUS.Canada),
    > # NOT as Dates
    > fda::matplot(earlyUS.Canada, Y)
    > # problem fixed.


    > # POSIXct
    > AmRev.ct <- as.POSIXct1970(c('1776-07-04', '1789-04-30'))
    > graphics::matplot(AmRev.ct, Y)
    > # horizontal axis labeled per as.numeric(AmRev.ct),
    > # NOT as POSIXct
    > fda::matplot(AmRev.ct, Y)
    > # problem fixed.

    >       Comments?

first parts: see above; from there I hope it's already
clear that I am sympathetic to your proposal,
... but (there's alway a "but", ..)

Still, as Abby mentioned,  turning a simple function into the
default method of an S3 generic is easy to do, but comes with a
bit of cost, not just S3 dispatch which typically is negligable in
graphics, but a bit of maintenance cost and mostly in this case
the cost of breaking back compatibility by the improvement.
How many plots will change where people have already relied on
the current   as.numeric(x)   behavior?
If we'd change this in R's graphics, it will be
- me and/or the CRAN team who have to contact CRAN package
  maintainer about problems
  (maybe none, as the change may not break any checks)

- Users of matplot() {& matlines() & matpoints()}  who may have to
  adopt their calls to these functions {I'm pretty sure all
  three would have to change for consistency}.

----- and then, there are quite a few other changes,  bug
      assignments to which I have committed which should be
      dealt with rather before this.

If you'd turn this into a proper "wishlist"  "bug" report
on R's bugzilla, *and* you or another volunteer provided a patch
to the R sources (including changes to man/*.Rd, NAMESPACE, ..)
which then can be tested to pass 'make check-all',
then I'd definitely commit to this
(possibly too late for R 4.0.0;  teaching starts here soon, etc).

Best,
Martin

    >       Thanks again for the reply.
    >       Spencer Graves
    >>
    >> B.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Spencer Graves-3


On 2020-01-28 05:13, Martin Maechler wrote:
>>>>>> Spencer Graves
>>>>>>      on Mon, 27 Jan 2020 23:02:28 -0600 writes:

<snip>

>
> Still, as Abby mentioned,  turning a simple function into the
> default method of an S3 generic is easy to do, but comes with a
> bit of cost, not just S3 dispatch which typically is negligable in
> graphics, but a bit of maintenance cost and mostly in this case
> the cost of breaking back compatibility by the improvement.
> How many plots will change where people have already relied on
> the current   as.numeric(x)   behavior?
> If we'd change this in R's graphics, it will be
> - me and/or the CRAN team who have to contact CRAN package
>    maintainer about problems
>    (maybe none, as the change may not break any checks)
>
> - Users of matplot() {& matlines() & matpoints()}  who may have to
>    adopt their calls to these functions {I'm pretty sure all
>    three would have to change for consistency}.
>
> ----- and then, there are quite a few other changes,  bug
>        assignments to which I have committed which should be
>        dealt with rather before this.
>
> If you'd turn this into a proper "wishlist"  "bug" report
> on R's bugzilla, *and* you or another volunteer provided a patch
> to the R sources (including changes to man/*.Rd, NAMESPACE, ..)
> which then can be tested to pass 'make check-all',
> then I'd definitely commit to this
> (possibly too late for R 4.0.0;  teaching starts here soon, etc).


       1.  What do you suggest I do to get acceptable copies of
~man/matplot.Rd and ~R/matplot.R -- and preferably the entire "graphics"
package, so I can do R CMD build, check, etc., as I've done for 15 years
or so with other R packages?


       2.  Then you'd like me to revise matplot.Rd to include
appropriate examples that work fine with fda::matplot but malfunction
with graphics::malfunction, then revise matplot.R so it fixed the
problem?  And you want a fix that does NOT convert "matplot" to generic,
and retains the current "as.numeric(x)" step except when inherits(x,
"Date") or inherits(x, "POSIXct")?


       3.  Then you want me to submit a "wishlist" "bug" report to
"https://bugs.r-project.org/bugzilla/index.cgi" including all changes to
matplot.Rd and matplot.R?  If I don't convert "matplot" to generic, then
there should be no need for changes to NAMESPACE, correct?


       An answer to question "1" with "yes" to questions "2" and "3"
should get me started.


       Thanks,
       Spencer Graves
>
> Best,
> Martin
>
>      >       Thanks again for the reply.
>      >       Spencer Graves
>      >>
>      >> B.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: matplot.Date & matplot.POSIXct

Martin Maechler
>>>>> Spencer Graves
>>>>>     on Tue, 28 Jan 2020 17:24:14 -0600 writes:

    > On 2020-01-28 05:13, Martin Maechler wrote:
    >>>>>>> Spencer Graves
    >>>>>>> on Mon, 27 Jan 2020 23:02:28 -0600 writes:

    > <snip>
    >>
    >> Still, as Abby mentioned,  turning a simple function into the
    >> default method of an S3 generic is easy to do, but comes with a
    >> bit of cost, not just S3 dispatch which typically is negligable in
    >> graphics, but a bit of maintenance cost and mostly in this case
    >> the cost of breaking back compatibility by the improvement.
    >> How many plots will change where people have already relied on
    >> the current   as.numeric(x)   behavior?
    >> If we'd change this in R's graphics, it will be
    >> - me and/or the CRAN team who have to contact CRAN package
    >> maintainer about problems
    >> (maybe none, as the change may not break any checks)
    >>
    >> - Users of matplot() {& matlines() & matpoints()}  who may have to
    >> adopt their calls to these functions {I'm pretty sure all
    >> three would have to change for consistency}.
    >>
    >> ----- and then, there are quite a few other changes,  bug
    >> assignments to which I have committed which should be
    >> dealt with rather before this.
    >>
    >> If you'd turn this into a proper "wishlist"  "bug" report
    >> on R's bugzilla, *and* you or another volunteer provided a patch
    >> to the R sources (including changes to man/*.Rd, NAMESPACE, ..)
    >> which then can be tested to pass 'make check-all',
    >> then I'd definitely commit to this
    >> (possibly too late for R 4.0.0;  teaching starts here soon, etc).


    >       1.  What do you suggest I do to get acceptable copies of
    > ~man/matplot.Rd and ~R/matplot.R -- and preferably the entire "graphics"
    > package, so I can do R CMD build, check, etc., as I've done for 15 years
    > or so with other R packages?

Getting the full source of R, either

1) from svn.r-project.org :

        svn checkout https://svn.r-project.org/R/trunk R-devel

   where the R source is maintained, or more easily if you have never
   worked with 'svn'
2) if you know git well, you can use the github *mirror* of svn.r-project.org,
  at https://github.com/wch/r-source/

3) most easily for most :  as tarball from CRAN

   wget https://cloud.r-project.org/src/base-prerelease/R-devel.tar.gz

   tar xf R-devel.tar.gz
   cd R-devel
   ls -lt src/library/graphics/{R,man}/matplot*


    >       2.  Then you'd like me to revise matplot.Rd to include
    > appropriate examples that work fine with fda::matplot but malfunction
    > with graphics::malfunction, then revise matplot.R so it fixed the
    > problem?  And you want a fix that does NOT convert "matplot" to generic,
    > and retains the current "as.numeric(x)" step except when inherits(x,
    > "Date") or inherits(x, "POSIXct")?

well... this would be for you or anybody else who'd like to help
the R project advance here.

HOWEVER, see below ..

    >       3.  Then you want me to submit a "wishlist" "bug" report to
    > "https://bugs.r-project.org/bugzilla/index.cgi" including all changes to
    > matplot.Rd and matplot.R?  If I don't convert "matplot" to generic, then
    > there should be no need for changes to NAMESPACE, correct?

that's correct.

However:  Thanks to the R-devel conversation with you, my
          thoughts have continued after writing my previous
          e-mail, and I've started to look into the source,
          i.e., matplot.R,

*and* worked out the solution myself: It now looks as I've been
able to change matplot() such that it typically does *not* use
matrix() nor as.matrix() for input 'x' of class "Date" or
"POSIXct" (or many similar S3 objects x) but rather uses the

          dim(x) <- c(n, m)

trick to turn x into a matrix .. which BTW does work for fine to
turn "Date" or "POSIXct" into matrices though you do *not* notice
that (!!) from print()ing them nor from str(.) --- the latter IMO
a buglet in the corresponding str() method).

I've spent some time to ensure matplot(x) continues to work when
'x' is a numeric data frame or a Matrix-package sparse matrix, etc,

I've run checks and will do some more but plan to commit this
version of matplot() to  R-devel within a few days,
so there's no need for now for anybody else to work on this.

Martin


    >       An answer to question "1" with "yes" to questions "2" and "3"
    > should get me started.

which for now should not be necessary:

I attach a cut'n'paste version of  my new (not yet committed)
version of matplot() for you to test (file name 'matplot-1.R')

Best, Martin


matplot <- function(x, y, type = "p",
                    lty = 1:5, lwd = 1, lend = par("lend"),
                    pch = NULL, col = 1:6, cex = NULL, bg = NA,
                    xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL,
                    log = "",
                    ..., add = FALSE, verbose = getOption("verbose"))
{
    paste.ch <- function(chv) paste0('"',chv,'"', collapse=" ")
    str2vec <- function(string) {
        if(nchar(string, type="c")[1L] > 1L) strsplit(string[1L], NULL)[[1L]]
        else string
    }
    ## These from plot.default :
    xlabel <- if (!missing(x)) deparse1(substitute(x))# else NULL
    ylabel <- if (!missing(y)) deparse1(substitute(y))
    ##
    if(missing(x)) {
        if(missing(y)) stop("must specify at least one of 'x' and 'y'")
        else x <- seq_len(NROW(y))
    } else if(missing(y)) {
        y <- x;  ylabel <- xlabel
        x <- seq_len(NROW(y)); xlabel <- ""
    }
    ## To preserve class, typically don't use as.matrix() or matrix() but only `dim<-`:
    if(is.matrix(x)) {
        n <- nrow(x)
    } else if(!is.null(dim(x))) { # matrix-like: data.frame, sparseMatrix, ..
        n <- nrow(x <- as.matrix(x))
    } else {
        n <- length(x)
        dim(x) <- c(n, 1L)
    }
    if(is.matrix(y)) {
        ## nothing
    } else if(!is.null(dim(y))) { # matrix-like
        y <- as.matrix(y)
    } else {
        dim(y) <- c(length(y), 1L)
    }
    if(n != nrow(y)) stop("'x' and 'y' must have same number of rows")
    kx <- ncol(x)
    ky <- ncol(y)
    if(kx != 1L && ky != 1L && kx != ky)
        stop("'x' and 'y' must have only 1 or the same number of columns")
    k <- max(kx, ky)

    type <- str2vec(type)
    if(is.null(pch)) {
        pch <- c(1L:9L, 0L, letters, LETTERS)
        if(k > length(pch) && any(type %in% c("p","o","b")))
            warning("default 'pch' is smaller than number of columns and hence recycled")
    } else if(is.character(pch)) pch <- str2vec(pch)
    ## else pch is numeric supposedly
    if(verbose)
        message("matplot: doing ", k, " plots with ",
                paste0(" col= (", paste.ch(col), ")"),
                paste0(" pch= (", paste.ch(pch), ")"),
                " ...\n", domain=NA)
    xy <- xy.coords(x, y, xlabel, ylabel, log = log, recycle=TRUE) # recycle if kx or ky is 1
    if(is.null(xlab)) xlab <- xy$xlab
    if(is.null(ylab)) ylab <- xy$ylab
    if(is.null(xlim)) xlim <- range(xy$x[is.finite(xy$x)])
    if(is.null(ylim)) ylim <- range(xy$y[is.finite(xy$y)])
    if(length(type)< k) type <- rep_len(type,k)
    if(length(lty) < k) lty  <- rep_len(lty, k)
    if(length(lend)< k) lend <- rep_len(lend,k)
    ## sciplot passes NULL
    if(length(lwd) < k && !is.null(lwd)) lwd <- rep_len(lwd, k)
    if(length(pch) < k) pch <- rep_len(pch, k)
    if(length(col) < k) col <- rep_len(col, k)
    if(length(bg)  < k) bg  <- rep_len(bg,  k)
    ## should not be able to call rep() on NULL
    if(is.null(cex)) cex <- 1
    if(length(cex) < k) cex <- rep_len(cex, k)
    ii <- seq_len(k)
    dev.hold(); on.exit(dev.flush())
    if(!add) {
        ii <- ii[-1L]
        plot(x[, 1L],y[, 1L], type = type[1L], xlab = xlab, ylab = ylab,
             xlim  =  xlim, ylim  =  ylim, lty = lty[1L], lwd = lwd[1L],
             lend = lend[1L], pch = pch[1L], col = col[1L], cex = cex[1L],
             bg = bg[1L], log = log, ...)
    }
    for (i in ii)
        lines(x[, 1L + (i-1L) %% kx], y[, 1L + (i-1L) %% ky],
              type = type[i], lty = lty[i], lwd = lwd[i],
              lend = lend[i], pch = pch[i], col = col[i], cex = cex[i],
              bg = bg[i])
    invisible()
}

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel