How to nicely rescale lattice figures?

后端 未结 2 897
说谎
说谎 2021-02-04 08:53

When preparing figures for printing I often need to make them much smaller than they appear on screen. It is not uncommon to have figures down to just a few cm across. With the

2条回答
  •  遇见更好的自我
    2021-02-04 09:09

    Intro

    There are several ways in which the size of elements of a lattice plot can be scaled. One option is to change all the parameters that take a cex attribute, the other is to change the base fontsize to which everything is drawn. The solution you want is the latter as you'll see in a minute, but it is also instructive to see how you can influence individual components of the plot via the par.settings argument as you may wish to tailor the relative scaling applied to individual components when setting fontsize.

    tl:dr

    Using the example plot from @Andrie's Answer

    require(lattice)
    plt <- xyplot(decrease ~ treatment, OrchardSprays, groups = rowpos,
                  type = "a",
                  auto.key = list(space = "right", points = FALSE, lines = TRUE))
    

    Set the fontsize parameter, a list with components text and points, which define the base sizes for these two key plot elements from which all other plot furniture is generated.

    update(plt, par.settings = list(fontsize = list(text = 8, points = 4)))
    

    enter image description here

    (as rendered on a 150px by 200px PNG raster device).

    Setting individual cex parameters for specific items of the plot furniture

    One of the things to notice is that the look of a Lattice plot is controlled by a whole stream of parameters as returned by trellis.par.get()

    > thm <- trellis.par.get()
    > str(thm, max = 1)
    List of 35
     $ grid.pars        : list()
     $ fontsize         :List of 2
     $ background       :List of 2
     $ panel.background :List of 1
     $ clip             :List of 2
     $ add.line         :List of 4
     $ add.text         :List of 5
     $ plot.polygon     :List of 5
     $ box.dot          :List of 5
     $ box.rectangle    :List of 5
     $ box.umbrella     :List of 4
     $ dot.line         :List of 4
     $ dot.symbol       :List of 5
     $ plot.line        :List of 4
     $ plot.symbol      :List of 6
     $ reference.line   :List of 4
     $ strip.background :List of 2
     $ strip.shingle    :List of 2
     $ strip.border     :List of 4
     $ superpose.line   :List of 4
     $ superpose.symbol :List of 6
     $ superpose.polygon:List of 5
     $ regions          :List of 2
     $ shade.colors     :List of 2
     $ axis.line        :List of 4
     $ axis.text        :List of 5
     $ axis.components  :List of 4
     $ layout.heights   :List of 19
     $ layout.widths    :List of 15
     $ box.3d           :List of 4
     $ par.xlab.text    :List of 5
     $ par.ylab.text    :List of 5
     $ par.zlab.text    :List of 5
     $ par.main.text    :List of 5
     $ par.sub.text     :List of 5
    

    Many of which effect the size of the objects drawn and text used in annotations. You need to modify all of the appropriate settings and pass only those as a list to par.settings(). Here is an example of scaling @Andrie's example plot:

    CEX <- 0.5
    
    pset <- list(superpose.symbol = list(cex = CEX),
                 plot.symbol      = list(cex = CEX),
                 par.sub.text     = list(cex = CEX),
                 par.main.text    = list(cex = CEX),
                 par.zlab.text    = list(cex = CEX),
                 par.ylab.text    = list(cex = CEX),
                 par.xlab.text    = list(cex = CEX),
                 dot.symbol       = list(cex = CEX),
                 box.dot          = list(cex = CEX),
                 add.text         = list(cex = CEX),
                 axis.text        = list(cex = CEX))
    plt2 <- update(plt, par.settings = pset)
    

    Using the gridExtra package to arrange two lattice plots on the same device we can see the effect of all of this:

    require("gridExtra")  ## loads package:grid too
    grid.arrange(plt, plt2, ncol = 2)
    

    resulting in

    enter image description here

    So now (almost) everything has been scaled. one interesting thing to note is that this approach hasn't scaled the length of the lines in the legend nor the tick lengths. Note the size of the plot the areas for each sub-plot were the same. We can however plot the whole thing at a much smaller size:

    enter image description here

    Which is reasonable, and will look better rendered on a vector-based device (e.g. pdf()) than the raster png() I have had to use to illustrate here. The second plot is on a 150px by 200px device.

    Setting the base fontsize to control overall scaling

    There is a simpler way and that is to set the base fontsize for text and points via the fontsize parameter. The default of which are:

    > trellis.par.get("fontsize")
    $text
    [1] 12
    
    $points
    [1] 8
    

    These affect everything on the plot, so we can shrink these to achieve a similar effect of setting all those other settings.

    update(plt, par.settings = list(fontsize = list(text = 8, points = 4)))
    

    which produces

    enter image description here

    This is plotted on the same sized png() device as Figure 2 from earlier. Notice how the margins have adjust so that the plot is better scaled. So not only have we affected all the settings we changed earlier, we have also affected the other bits of the plot (such as spacing and tick marks) that also take their queue from the fontsize settings. Again, plotting these on a vector device will produce better output.

提交回复
热议问题