[R] Garbled plot label

Marc Schwartz MSchwartz at MedAnalytics.com
Mon Apr 25 16:20:33 CEST 2005


On Mon, 2005-04-25 at 15:24 +0200, Roger Bivand wrote:
> On Mon, 25 Apr 2005, Henric Nilsson wrote:
> 
> > Uwe Ligges said the following on 2005-04-25 10:22:
> > > Maciej BliziÃ±ski wrote:
> > > 
> > >> Hello,
> > >>
> > >> While using the "plot" function against a model with a long formula,
> > >> I get a garbled label in the bottom of the plot. It looks like there are
> > >> two lines printed one over another, here's my example:
> > >>
> > >> http://pico.magnum2.pl/maciej/NodalInvolvement/MisclassificationRate?action=AttachFile&do=get&target=TwoFactorResiduals.png 
> > >>
> > >>
> > >> This was from using  "plot(model_object)" which produces 4 plots at
> > >> once. Can I fix it somehow?
> > >>
> > >> I already tried googling, and searching R maillist archives and didn't
> > >> find a relevant discussion.
> > >>
> > > 
> > > Can you provide a reproducible example please (the posting guide ask to 
> > > do so anyway)?
> > 
> > It's quite easy to reproduce this. Just
> > 
> > long.var.name.1 <- runif(10)
> > long.var.name.2 <- runif(10)
> > long.var.name.3 <- runif(10)
> > long.var.name.4 <- runif(10)
> > fit <- lm(long.var.name.1 ~ long.var.name.2 + long.var.name.3 + 
> > long.var.name.4)
> > plot(fit)
> > 
> 
> To remove the problem in the plot, do:
> 
> plot(fit, sub.caption="")
> 
> As it is, sub.caption = deparse(x$call) by default, and
> 
> > deparse(fit$call)
> [1] "lm(formula = long.var.name.1 ~ long.var.name.2 + long.var.name.3 + "
> [2] "    long.var.name.4)"
> 
> so this is two lines on top of each other. Unrolling:
> 
> plot(fit, sub.caption=gsub("[ ]+", " ", paste(deparse(fit$call), collapse="")))
> 
> still works, but is becoming very long. Would a better default perhaps be 
> the name of the first argument?
> 
> Roger


Here is another option. One issue is that given the way in which plot.lm
() is coded, some of the axis labels are hard coded when passed to the
four underlying plot functions and as far as I can tell, there is no way
to use a 'par' and just blank out the x axis labels only. Thus, both x
and y axis labels need to be blanked and then separately created using
title().

Thus, here is a plot.lm2() function. It's a bit kludgy, but it seems to
work, though other eyes should look at it for any errors.

What it effectively does is to do each of the four plots in plot.lm()
individually without labels (ann = FALSE) and then adds them, generally
based upon the way it is done in plot.lm(). The x axis labels are paste
()'d to the wrapped model expression to create a multi-line sub.title
for each plot.

The wrap.len argument is the 'width' argument for strwrap indicating the
target line wrapping length. Note that if you get to around 3 lines, you
will likely need to modify the margins in the plot for side 1 to provide
for more room.



plot.lm2 <- function(x, wrap.len = 60)
{
  sub.caption <- paste(deparse(x$call, wrap.len), collapse = "\n")
  isGlm <- inherits(x, "glm")
  ylab23 <- if (isGlm) 
              "Std. deviance resid."
            else "Standardized residuals"
  l.fit <- if (isGlm) 
            "Predicted values"
           else "Fitted values"

  par(ask = TRUE)

  
  # plot #1: Residuals vs Fitted
  plot(x, which = 1, ann = FALSE, sub.caption = NULL)
  title(sub = paste(l.fit, sub.caption, sep = "\n"),
        ylab = "Residuals")


  # plot #2: Normal Q-Q plot
  plot(x, which = 2, ann = FALSE, sub.caption = NULL)
  xlab <- "Theoretical Quantiles"
  title(sub = paste(xlab, sub.caption, sep = "\n"),
        ylab = ylab23)

  
  # plot #3: Scale-Location plot
  plot(x, which = 3, ann = FALSE, sub.caption = NULL)
  yl <- as.expression(substitute(sqrt(abs(YL)),
                      list(YL = as.name(ylab23))))
  title(sub = paste(l.fit, sub.caption, sep = "\n"),
        ylab = yl)

  
  # plot #4: Cook's distance plot
  plot(x, which = 4, ann = FALSE, sub.caption = NULL)
  xlab <- "Obs. number"
  title(sub = paste(xlab, sub.caption, sep = "\n"),
        ylab = "Cook's distance")
}


Using the model that Henric created in his post, you can call the
modified function as:

plot.lm2(fit, 60)

to see the effect of wrapping the x axis label to two lines.

HTH,

Marc Schwartz




More information about the R-help mailing list