>>>>> 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