R-alpha: Minor plotting problems [improved hist()]

Martin Maechler Martin Maechler <maechler@stat.math.ethz.ch>
Fri, 31 Oct 1997 19:36:48 +0100


>>>>> "Peter" == Peter Dalgaard BSA <p.dalgaard@kubism.ku.dk> writes:

    Peter> 1) There's a curious asymmetry between points and lines, in that
    Peter> you can do lines(...,type='p') but not points(...,type='l') (and
    Peter> more importantly, not points(..., type='b'), which probably
    Peter> *could* arise in real work)

Now fixed in current source.

    Peter> 2) Did I remember to report the adverse effect of having
    Peter> plot(x,y) coerce its argument to numeric? Several of my students
    Peter> managed to set the data type to "character" in data.entry(), do
    Peter> a plot(bw,rmr) with no apparent problem, and *then* become
    Peter> absolutely perplexed when lm(rmr~bw) yields

    Peter> Error in model.frame(formula, data, substitute(list(...)),
    Peter> subset, na.action) : invalid variable type

I agree that plot  shouldn't coerce character x / y to numeric.
Nothing yet done.
	[Peter,  you can do the changes if you like ..]


    Peter> 3) The first few lines of hist() should be

    Peter>         if (!is.numeric(x)) stop("hist: x must be numeric")
    Peter> eval(main) eval(xlab) x <- x[!is.na(x)]
 
    Peter> The two 'eval's are necessary to avoid strange side effects of
    Peter> modifying x.

Ok, I've done quite a bit more. 

hist is ``better'' now
	 [[the ``nclass'' discussion is not yet done ... !]]:  

	1) allows  `plot = FALSE'  [as S; but really IS useful]
	2) Default for 'freq:  TRUE only if breaks are equispaced
			(otherwise the plot is graphically *WRONG*)

The following is now in 0.60 :

"hist" <-
function (x, breaks, freq = NULL, col = NULL, border = par("fg"),
	main = paste("Histogram of" , deparse(substitute(x))),
	xlim = range(breaks), ylim = range(counts, 0),
	xlab = deparse(substitute(x)), ylab,
	axes=TRUE, plot = TRUE, ...)
{
	if (!is.numeric(x)) 
		stop("hist: x must be numeric")
	eval(main)
	eval(xlab)
	n <- length(x <- x[!is.na(x)])
	use.br <- !missing(breaks) && length(breaks) > 1
	breaks <-
	  if(use.br) sort(breaks)
	  else {
		rx <- range(x)
		pretty (rx + c(0, diff(rx)/1000), 
			n = if(missing(breaks)) 1 + log2(n)
			else { # breaks = `nclass'	
				if (is.na(breaks) | breaks < 2) 
				  stop("invalid number of breaks")
				breaks
			})
	  }
	nB <- length(breaks)
	counts <- .C("bincount", 
		as.double(x), 
		n, 
		as.double(breaks), 
		nB,
		counts = integer(nB - 1), 
		NAOK = FALSE) $counts
	if (any(counts < 0)) 
	 stop("negative `counts'. Internal Error in C-code for \"bincount\"")
	if (is.null(freq)) 
	  freq <- if(use.br) {
		##-- Do frequencies if breaks are evenly spaced ...
		h <- diff(breaks)
		diff(range(h)) < 1e-10 * h
	  } else TRUE
	if (!freq) {
		counts <- counts/(sum(x) * diff(breaks))
		if (missing(ylab)) 
			ylab <- "Relative Frequency"
	}
	else if (missing(ylab)) 
		ylab <- "Frequency"
	if(plot) {
		plot.new()
		plot.window(xlim, ylim, "")
		title(main = main, xlab = xlab, ylab = ylab, ...)
		if(axes) {
			axis(1, ...)
			axis(2, ...)
		}
		rect(breaks[-length(breaks)], 0, breaks[-1], counts,
		     col = col, border = border)
		invisible(NULL)
	} else list(breaks = breaks, counts = counts)
}
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-devel-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=