[R] Positioning in xyplot

Deepayan Sarkar deepayan.sarkar at gmail.com
Wed Apr 11 22:55:30 CEST 2007


On 4/11/07, Sundar Dorai-Raj <sundar.dorai-raj at pdf.com> wrote:

> Seems like you may get a workaround (albeit kludgey) by using
> ?print.trellis. Here's another example:
>
> library(lattice)
> z <- expand.grid(x = 1:10, p = 1:5, r = 1:10)
> z$y <- rnorm(nrow(z))
> z$p <- factor(z$p, levels = c(1, 5, 2, 4, 3))
> bot <- xyplot(y ~ x | p, z, groups = r,
>                layout = c(2, 2), type = "l",
>                scales = list(alternating = 1),
>                subset = p != 3)
> top <- xyplot(y ~ x | p, z, groups = r,
>                type = "l", xlab = "",
>                scales = list(alternating = 2),
>                subset = p == 3)
>
> print(bot, c(0, 0, 1, 11/16))
> print(top, c(1/5, 7/12, 4/5, 1), newpage = FALSE)

Here's another hack (thanks to Sundar for the reproducible example):



library(grid)

## this is a safer version of current.panel.limits()

current.limits <-
    function ()
{
    xlim <- convertX(unit(c(0, 1), "npc"), "native", valueOnly = TRUE)
    ylim <- convertY(unit(c(0, 1), "npc"), "native", valueOnly = TRUE)
    if (any(!is.finite(xlim))) xlim <- c(0, 1)
    if (any(!is.finite(ylim))) ylim <- c(0, 1)
    list(xlim = xlim, ylim = ylim)
}

## this calls 'fun' after moving its viewport if panel.number() == 5

callAfterMoving <-
    function(fun, border = TRUE, move.x = 1, ...)
{
    if (panel.number() == 5) {
        fun(...)
        if (border) grid.rect()
    }
    else {
        cpl <- current.limits()
        pushViewport(viewport(x = move.x,
                              width = unit(1, "npc"),
                              xscale = cpl$xlim,
                              yscale = cpl$ylim,
                              clip = "off"))
        fun(...)
        if (border) grid.rect()
        upViewport()
    }
}


## this almost works, except for the axes on the left, because in the
## context in which it is drawn (the strip on the left, invisible in
## this example), information about how much to move right is not
## available.


xyplot(y ~ x | p, z, groups = r,
       layout = c(2, 3), type = "l",
       par.settings =
       list(axis.line = list(col = "transparent"),
            strip.border = list(col = "transparent")),
       panel = function(...) {
           callAfterMoving(panel.xyplot, ...)
       },
       strip = function(...) {
           callAfterMoving(strip.default, ...)
       },
       axis = function(..., line.col) {
           callAfterMoving(axis.default,
                           border = FALSE,
                           line.col = 'black',
                           ...)
       })


## one way to bail out is simply not draw the left axes.  It can also be
## added back explicitly by adding a call to panel.axis inside the
## panel function (see below)


xyplot(y ~ x | p, z, groups = r,
       layout = c(2, 3), type = "l",
       par.settings =
       list(axis.line = list(col = "transparent"),
            strip.border = list(col = "transparent")),
       panel = function(...) {
           callAfterMoving(panel.xyplot, ...)
       },
       strip = function(...) {
           callAfterMoving(strip.default, ...)
       },
       axis = function(..., line.col, side) {
           if (side != "left" || panel.number() != 5) {
               callAfterMoving(axis.default,
                               border = FALSE,
                               line.col = 'black',
                               side = side,
                               ...)
           }
       })


## panel function with axes on the left:

panel.leftaxes <- function(...)
{
    if (panel.number() == 5)
       panel.axis("left", outside = TRUE,
                   line.col = "black")
    panel.xyplot(...)
}


xyplot(y ~ x | p, z, groups = r,
       layout = c(2, 3), type = "l",
       par.settings =
       list(axis.line = list(col = "transparent"),
            strip.border = list(col = "transparent")),
       panel = function(...) {
           callAfterMoving(panel.leftaxes, ...)
       },
       strip = function(...) {
           callAfterMoving(strip.default, ...)
       },
       axis = function(..., line.col, side) {
           if (side != "left" || panel.number() != 5) {
               callAfterMoving(axis.default,
                               border = FALSE,
                               line.col = 'black',
                               side = side,
                               ...)
           }
       })

-Deepayan



More information about the R-help mailing list