[R] Unintended behaviour (possibly bugs)
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Thu Mar 12 18:15:53 CET 2020
>>>>> Alexey Shipunov
>>>>> on Tue, 18 Feb 2020 14:34:48 +0900 writes:
> Thank you for the detailed explanation. I tend to agree. However, this
> behavior is relatively easy to remediate:
> This is the piece of the current code:
> ===
> if (!(is.null(labels) && is.null(glabels))) {
> nmai <- par("mai")
> nmai[2L] <- nmai[4L] + max(linch + goffset, ginch) + 0.1
> par(mai = nmai)
> }
> ===
> This is my proposal:
> ===
> yinch <- if (!is.null(ylab)) 0.4 else 0
> if (!(is.null(labels) && is.null(glabels))) {
> nmai <- par("mai")
> nm.2 <- nmai[4L] + max(if(is.null(ylab)) 0 else 0.4) + linch + goffset, ginch) + 0.1
> if (nmai[2L] < nm.2)
> nmai[2L] <- nm.2
> par(mai = nmai)
> }
> ===
> Then margins and y-axis labels start to work normally. I wonder if
> this (or similar) is possible to introduce into the code?
> Alexey
Well, I had looked at this back then (~Feb 18), and now had a
considerable longer look.
Your suggestion makes sense, but then it needs even more work
to ensure that the 'ylab' y-axis label will be placed properly.
Of course, Deepayan (author of grid-based 'lattice') is right
that dotchart()s implementation is pretty hackish ... but then
still.
I have (+-) fixed this in the sources of "R-devel" the
development version of R (which should become R 4.0.0 on April
24 as was announced today).
Now, things like this (extended) example work nicely :
op <- par(xaxs = "i") # 0 -- 100\%
dotchart(t(VADeaths), xlim = c(0,100), bg = "skyblue",
main = "Death Rates in Virginia - 1940", xlab = "rate [ % ]",
ylab = "Grouping: Age x Urbanity . Gender")
par(op)
Thank you, Alexey, for your report and bug fix suggestion!
Best regards,
Martin Maechler
ETH Zurich and R Core team
> ........... 17:37, Deepayan Sarkar <deepayan.sarkar using gmail.com>:
>>
>> On Mon, Feb 17, 2020 at 10:24 AM Rui Barradas <ruipbarradas using sapo.pt> wrot=
> e:
>> >
>> > Hello,
>> >
>> > Yes, this is definitely a bug.
>>
>> I would argue that the only bug here is that the documentation doesn't
>> say that 'ylab' may not behave as expected.
>>
>> dotchart() is mainly designed for 2-way tables (see the VADeaths
>> example), but it's implementation is really pretty hackish because it
>> has to work within the limited traditional graphics framework. The
>> main problem is that dot plots want to put horizontal y-axis labels
>> (usually derived from factor levels), which are often longer than the
>> default margins, so the margins are modified. Unfortunately they are
>> only re-set on exit, and so the ylab that is plotted inside dotchart()
>> may be clipped. Traditionally, Cleveland dot plots don't have a y-axis
>> label; it's assumed that the factor levels are sufficient (and for
>> 2-way tables, there would be two variables, so there is no sensible
>> default).
>>
>> I doubt that dotchart() is worth fixing (except to maybe disallow
>> ylab). If you want flexibility, use modern grid-based alternatives
>> such as lattice::dotplot() or ggplot2.
>>
>> -Deepayan
>>
>> > Even the matrix plot is puzzling, with a "1" as top row sort-of-label
>> > but no grid line. I'm trying to follow the source code of dotchart but
>> > am yet to understand exactly what it does to decide the margins setting=
> s.
>> >
>> > if (!(is.null(labels) && is.null(glabels))) {
>> > nmai <- par("mai")
>> > nmai[2L] <- nmai[4L] + max(linch + goffset, ginch) +
>> > 0.1
>> > par(mai = nmai)
>> > }
>> >
>> > This should be moved to r-devel?
>> >
>> > Rui Barradas
>> >
>> > 03:33 de 17/02/20, Alexey Shipunov escreveu:
>> > > John and Rui, thanks!
>> > >
>> > > However, if we use the proper object, the problem still persists:
>> > >
>> > > dotchart(c("3"=1, "2"=2, "1"=3), ylab="Ylab") # ylab is invisible
>> > > dotchart(c("aa"=1, "b"=2, "cc"=3), ylab="Ylab") # ylab is partly visible (!!!)
>> > > dotchart(c("aaa"=1, "bbb"=2, "ccc"=3), ylab="Ylab") # ylab is well visible
>> > >
>> > > If the object is matrix, ylab is visible:
>> > >
>> > > dotchart(matrix(1:3, dimnames=list(c("aa","bb","cc"), NULL)), ylab="Ylab")
>> > >
>> > > But the ?dotchart explicitly says that "x: either a vector or matrix
>> > > of numeric values" and then "labels: a vector of labels for each
>> > > point. For vectors the default is to use "names(x) = ...".
>> > >
>> > > So this is likely a bug. Do you agree?
>> > >
>> > > Alexey
>> > >
>> > > ..... 01:55, Rui Barradas <ruipbarradas using sapo.pt>:
>> > >>
>> > >> Hello,
>> > >>
>> > >> I believe you are wrong, the error is not in dotchart, it's in your
>> > >> code. You assume that to plot an object of class "table" is the same as
>> > >> to plot an object of class "numeric".
>> > >>
>> > >> Inline.
>> > >>
>> > >> =C3=80s 12:21 de 16/02/20, Alexey Shipunov escreveu:
>> > >>> Dear list,
>> > >>>
>> > >>> I have been advised to share these with R-help instead of filling the
>> > >>> bug report:
>> > >>>
>> > >>> 1) dotchart() does not allow to see the left axis title ('ylab') and
>> > >>> cannot change the left margin (outer margin 2) of the plot
>> > >>>
>> > >>> The code:
>> > >>>
>> > >>> aa <- table(c(1, 1, 1, 2, 2, 3))
>> > >>> dotchart(aa, ylab="Ylab") # does not show 'ylab'
>> > >>
>> > >> You are right, it does *not* show 'ylab' but the user is warned.
>> > >>
>> > >>
>> > >> aa <- table(c(1, 1, 1, 2, 2, 3))
>> > >> dotchart(aa, ylab = "Ylab") # does show 'ylab'
>> > >> #Warning message:
>> > >> #In dotchart(aa, ylab = "Ylab") :
>> > >> # 'x' is neither a vector nor a matrix: using as.numeric(x)
>> > >>
>> > >>
>> > >> My code:
>> > >>
>> > >>
>> > >> (mar <- par("mar")) # new R session
>> > >> #[1] 5.1 4.1 4.1 2.1 # the left margin is 4.1
>> > >>
>> > >> aa <- as.numeric(table(c(1, 1, 1, 2, 2, 3)))
>> > >>
>> > >> dotchart(aa, ylab = "Ylab") # It does show 'ylab'
>> > >> old.par <- par(mar = mar + c(0, 5, 0, 0))
>> > >> par("mar")
>> > >> #[1] 5.1 9.1 4.1 2.1
>> > >>
>> > >> dotchart(aa, ylab = "Ylab") # The left margin is now 9.1, much bigger
>> > >>
>> > >> par(old.par) # It does change the left margin
>> > >> dotchart(aa, ylab = "Ylab") # but only when a new graph is plotted.
>> > >>
>> > >>
>> > >>
>> > >>> old.par <- par(mar=c(1, 10, 1, 1)) ; dotchart(aa, ylab="Ylab") ;
>> > >>> par(old.par) # does not change left margin
>> > >>>
>> > >>> Possible solution:
>> > >>>
>> > >>> I researched the problem and think that the dotchart() code will need
>> > >>> few corrections. If there is an interest, I can post it here; or you
>> > >>> can look at the code of shipunov::Dotchart1() function.
>> > >>>
>> > >>> 2) example(hist) includes two "wrong" and "extreme" examples which
>> > >>> slow down and even crash R on some systems; this make it unsuitable
>> > >>> for demonstration in the class and strikes beginners in R who just
>> > >>> want to understand how hist() works. Actually, I did it last week (I
>> > >>> was not aware of these examples), and in the class two computers hang,
>> > >>> and many others were extremely slow.
>> > >>>
>> > >>> The code:
>> > >>>
>> > >>> example(hist)
>> > >>>
>> > >>> Possible solution:
>> > >>>
>> > >>> If R maintainers will enclose parts of "hist" example in \dontrun{},
>> > >>> this will allow to see the code but in the same time will not strike
>> > >>> beginners in R who just
>> > >>> want to understand how hist() works. They will still be possible to
>> > >>> run with example(..., run.dontrun=TRUE).
>> > >>
>> > >> Agree, it's annoying. Sometimes there's a Warning section after the
>> > >> Details section. Maybe such a section could get users' attention to
>> > >> those examples? At least it wouldn't hurt...
>> > >>
>> > >>
>> > >> Hope this helps,
>> > >>
>> > >> Rui Barradas
>> > >>
>> > >>>
>> > >>> With best wishes,
>> > >>>
>> > >>> Alexey Shipunov
>> > >>> ______________________________________________
More information about the R-help
mailing list