Functions to Interact with Lattice Plots

Description

The classic Trellis paradigm is to plot the whole object at once, without the possibility of interacting with it afterwards. However, by keeping track of the grid viewports where the panels and strips are drawn, it is possible to go back to them afterwards and enhance them one panel at a time. These functions provide convenient interfaces to help in this. Note that these are still experimental and the exact details may change in future.

Usage

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
panel.identify(x, y = NULL,
               subscripts = seq_along(x),
               labels = subscripts, 
               n = length(x), offset = 0.5,
               threshold = 18, ## in points, roughly 0.25 inches
               panel.args = trellis.panelArgs(),
               ...)
panel.identify.qqmath(x, distribution, groups, subscripts, labels,
                      panel.args = trellis.panelArgs(),
                      ...)
panel.identify.cloud(x, y, z, subscripts,
                     perspective, distance, 
                     xlim, ylim, zlim,
                     screen, R.mat, aspect, scales.3d,
                     ...,
                     panel.3d.identify,
                     n = length(subscripts),
                     offset = 0.5,
                     threshold = 18,
                     labels = subscripts,
                     panel.args = trellis.panelArgs())
panel.link.splom(threshold = 18, verbose = getOption("verbose"), ...)
panel.brush.splom(threshold = 18, verbose = getOption("verbose"), ...)


trellis.vpname(name = c("position", "split", "split.location", "toplevel",
                        "figure", "panel", "strip", "strip.left",
                        "legend", "legend.region", "main", "sub",
                        "xlab", "ylab", "xlab.top", "ylab.right", "page"),
               column, row,
               side = c("left", "top", "right", "bottom", "inside"),
               clip.off = FALSE, prefix)
trellis.grobname(name,
                 type = c("", "panel", "strip", "strip.left",
                          "key", "colorkey"),
                 group = 0,
                 which.given = lattice.getStatus("current.which.given",
                                                 prefix = prefix),
                 which.panel = lattice.getStatus("current.which.panel",
                                                 prefix = prefix),
                 column = lattice.getStatus("current.focus.column",
                                            prefix = prefix),
                 row = lattice.getStatus("current.focus.row",
                                         prefix = prefix),
                 prefix = lattice.getStatus("current.prefix"))
trellis.focus(name, column, row, side, clip.off,
              highlight = interactive(), ..., prefix,
              guess = TRUE, verbose = getOption("verbose"))
trellis.switchFocus(name, side, clip.off, highlight, ..., prefix)
trellis.unfocus()
trellis.panelArgs(x, packet.number)

Arguments

x, y, z

variables defining the contents of the panel. In the case of trellis.panelArgs, a "trellis" object.

n

the number of points to identify by default (overridden by a right click)

subscripts

an optional vector of integer indices associated with each point. See details below.

labels

an optional vector of labels associated with each point. Defaults to subscripts

distribution, groups

typical panel arguments of panel.qqmath. These will usually be obtained from panel.args

offset

the labels are printed either below, above, to the left or to the right of the identified point, depending on the relative location of the mouse click. The offset specifies (in "char" units) how far from the identified point the labels should be printed.

threshold

threshold in grid's "points" units. Points further than these from the mouse click position are not considered

panel.args

list that contains components names x (and usually y), to be used if x is missing. Typically, when called after trellis.focus, this would appropriately be the arguments passed to that panel.

perspective, distance, xlim, ylim, zlim, screen, R.mat, aspect, scales.3d

arguments as passed to panel.cloud. These are required to recompute the relevant three-dimensional projections in panel.identify.cloud.

panel.3d.identify

the function that is responsible for the actual interaction once the data rescaling and rotation computations have been done. By default, an internal function similar to panel.identify is used.

name

A character string indicating which viewport or grob we are looking for. Although these do not necessarily provide access to all viewports and grobs created by a lattice plot, they cover most of the ones that end-users may find interesting.

trellis.vpname and trellis.focus deal with viewport names only, and only accept the values explicitly listed above. trellis.grobname is meant to create names for grobs, and can currently accept any value.

If name, as well as column and row is missing in a call to trellis.focus, the user can click inside a panel (or an associated strip) to focus on that panel. Note however that this assumes equal width and height for each panel, and may not work when this is not true.

When name is "panel", "strip", or "strip.left", column and row must also be specified. When name is "legend", side must also be specified.

column, row

integers, indicating position of the panel or strip that should be assigned focus in the Trellis layout. Rows are usually calculated from the bottom up, unless the plot was created with as.table=TRUE

guess

logical. If TRUE, and the display has only one panel, that panel will be automatically selected by a call to trellis.focus.

side

character string, relevant only for legends (i.e., when name="legend"), indicating their position. Partial specification is allowed, as long as it is unambiguous.

clip.off

logical, whether clipping should be off, relevant when name is "panel" or "strip". This is necessary if axes are to be drawn outside the panel or strip. Note that setting clip.off=FALSE does not necessarily mean that clipping is on; that is determined by conditions in effect during printing.

type

A character string specifying whether the grob is specific to a particular panel or strip.

When type is "panel", "strip", or "strip.left", information about the panel is added to the grob name.

group

An integer specifying whether the grob is specific to a particular group within the plot.

When group is greater than zero, information about the group is added to the grob name.

which.given, which.panel

integers, indicating which conditional variable is being represented (within a strip) and the current levels of the conditional variables.

When which.panel has length greater than 1, and the type is "strip" or "strip.left", information about the conditional variable is added to the grob name.

prefix

A character string acting as a prefix identifying the plot of a "trellis" object, primarily used to distinguish otherwise equivalent viewports in different plots. This only becomes relevant when a particular page is occupied by more than one plot. Defaults to the value appropriate for the last "trellis" object printed, as determined by the prefix argument in print.trellis.

Users should not usually need to supply a value for this argument except to interact with an existing plot other than the one plotted last.

For switchFocus, ignored except when it does not match the prefix of the currently active plot, in which case an error occurs.

highlight

logical, whether the viewport being assigned focus should be highlighted. For trellis.focus, the default is TRUE in interactive mode, and trellis.switchFocus by default preserves the setting currently active.

packet.number

integer, which panel to get data from. See packet.number for details on how this is calculated

verbose

whether details will be printed

...

For panel.identify.qqmath, extra parameters are passed on to panel.identify. For panel.identify, extra arguments are treated as graphical parameters and are used for labelling. For trellis.focus and trellis.switchFocus, these are used (in combination with lattice.options) for highlighting the chosen viewport if so requested. Graphical parameters can be supplied for panel.link.splom.

Details

panel.identify is similar to identify. When called, it waits for the user to identify points (in the panel being drawn) via mouse clicks. Clicks other than left-clicks terminate the procedure. Although it is possible to call it as part of the panel function, it is more typical to use it to identify points after plotting the whole object, in which case a call to trellis.focus first is necessary.

panel.link.splom is meant for use with splom, and requires a panel to be chosen using trellis.focus before it is called. Clicking on a point causes that and the corresponding proections in other pairwise scatter plots to be highlighted. panel.brush.splom is a (misnamed) alias for panel.link.splom, retained for back-compatibility.

panel.identify.qqmath is a specialized wrapper meant for use with the display produced by qqmath. panel.identify.qqmath is a specialized wrapper meant for use with the display produced by cloud. It would be unusual to call them except in a context where default panel function arguments are available through trellis.panelArgs (see below).

One way in which panel.identify etc. are different from identify is in how it uses the subscripts argument. In general, when one identifies points in a panel, one wants to identify the origin in the data frame used to produce the plot, and not within that particular panel. This information is available to the panel function, but only in certain situations. One way to ensure that subscripts is available is to specify subscripts = TRUE in the high level call such as xyplot. If subscripts is not explicitly specified in the call to panel.identify, but is available in panel.args, then those values will be used. Otherwise, they default to seq_along(x). In either case, the final return value will be the subscripts that were marked.

The process of printing (plotting) a Trellis object builds up a grid layout with named viewports which can then be accessed to modify the plot further. While full flexibility can only be obtained by using grid functions directly, a few lattice functions are available for the more common tasks.

trellis.focus can be used to move to a particular panel or strip, identified by its position in the array of panels. It can also be used to focus on the viewport corresponding to one of the labels or a legend, though such usage would be less useful. The exact viewport is determined by the name along with the other arguments, not all of which are relevant for all names. Note that when more than one object is plotted on a page, trellis.focus will always go to the plot that was created last. For more flexibility, use grid functions directly (see note below).

After a successful call to trellis.focus, the desired viewport (typically panel or strip area) will be made the ‘current’ viewport (plotting area), which can then be enhanced by calls to standard lattice panel functions as well as grid functions.

It is quite common to have the layout of panels chosen when a "trellis" object is drawn, and not before then. Information on the layout (specifically, how many rows and columns, and which packet belongs in which position in this layout) is retained for the last "trellis" object plotted, and is available through trellis.currentLayout.

trellis.unfocus unsets the focus, and makes the top level viewport the current viewport.

trellis.switchFocus is a convenience function to switch from one viewport to another, while preserving the current row and column. Although the rows and columns only make sense for panels and strips, they would be preserved even when the user switches to some other viewport (where row/column is irrelevant) and then switches back.

Once a panel or strip is in focus, trellis.panelArgs can be used to retrieve the arguments that were available to the panel function at that position. In this case, it can be called without arguments as

1
trellis.panelArgs()

This usage is also allowed when a "trellis" object is being printed, e.g. inside the panel functions or the axis function (but not inside the prepanel function). trellis.panelArgs can also retrieve the panel arguments from any "trellis" object. Note that for this usage, one needs to specify the packet.number (as described under the panel entry in xyplot) and not the position in the layout, because a layout determines the panel only after the object has been printed.

It is usually not necessary to call trellis.vpname and trellis.grobname directly. However, they can be useful in generating appropriate names in a portable way when using grid functions to interact with the plots directly, as described in the note below.

Value

panel.identify returns an integer vector containing the subscripts of the identified points (see details above). The equivalent of identify with pos=TRUE is not yet implemented, but can be considered for addition if requested.

trellis.panelArgs returns a named list of arguments that were available to the panel function for the chosen panel.

trellis.vpname and trellis.grobname return character strings.

trellis.focus has a meaningful return value only if it has been used to focus on a panel interactively, in which case the return value is a list with components col and row giving the column and row positions respectively of the chosen panel, unless the choice was cancelled (by a right click), in which case the return value is NULL. If click was outside a panel, both col and row are set to 0.

Note

The viewports created by lattice are accessible to the user through trellis.focus as described above. Functions from the grid package can also be used directly. For example, current.vpTree can be used to inspect the current viewport tree and seekViewport or downViewport can be used to navigate to these viewports. For such usage, trellis.vpname and trellis.grobname provides a portable way to access the appropriate viewports and grobs by name.

Author(s)

Deepayan Sarkar Deepayan.Sarkar@R-project.org. Felix Andrews provided initial implementations of panel.identify.qqmath and support for focusing on panels interctively.

See Also

identify, Lattice, print.trellis, trellis.currentLayout, current.vpTree, viewports

Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
## Not run: 
xyplot(1:10 ~ 1:10)
trellis.focus("panel", 1, 1)
panel.identify()

## End(Not run)

xyplot(Petal.Length ~ Sepal.Length | Species, iris, layout = c(2, 2))
Sys.sleep(1)

trellis.focus("panel", 1, 1)
do.call("panel.lmline", trellis.panelArgs())
Sys.sleep(0.5)
trellis.unfocus()

trellis.focus("panel", 2, 1)
do.call("panel.lmline", trellis.panelArgs())
Sys.sleep(0.5)
trellis.unfocus()

trellis.focus("panel", 1, 2)
do.call("panel.lmline", trellis.panelArgs())
Sys.sleep(0.5)
trellis.unfocus()


## choosing loess smoothing parameter

p <- xyplot(dist ~ speed, cars)

panel.loessresid <-
    function(x = panel.args$x,
             y = panel.args$y,
             span,
             panel.args = trellis.panelArgs())
{
    fm <- loess(y ~ x, span = span)
    xgrid <- do.breaks(current.panel.limits()$xlim, 50)
    ygrid <- predict(fm, newdata = data.frame(x = xgrid))
    panel.lines(xgrid, ygrid)
    pred <- predict(fm)
    ## center residuals so that they fall inside panel
    resids <- y - pred + mean(y)
    fm.resid <- loess.smooth(x, resids, span = span)
    ##panel.points(x, resids, col = 1, pch = 4)
    panel.lines(fm.resid, col = 1)
}


spans <- c(0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8)
update(p, index.cond = list(rep(1, length(spans))))
panel.locs <- trellis.currentLayout()

i <- 1

for (row in 1:nrow(panel.locs))
    for (column in 1:ncol(panel.locs))
    if (panel.locs[row, column] > 0)
{
    trellis.focus("panel", row = row, column = column,
                  highlight = FALSE)
    panel.loessresid(span = spans[i])
    grid::grid.text(paste("span = ", spans[i]),
                    x = 0.25,
                    y = 0.75,
                    default.units = "npc")
    trellis.unfocus()
    i <- i + 1
}

Want to suggest features or report bugs for rdrr.io? Use the GitHub issue tracker.