>>>>> 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() }
______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel