[R] Lattice: How to color the data points in splom() according to the panel they are plotted?

Martin Maechler maechler at stat.math.ethz.ch
Mon Jun 14 14:54:46 CEST 2010

Dear Deepayan,

this is in reply to a message almost 6 months ago :

>>>>> Deepayan Sarkar <deepayan.sarkar at gmail.com>
>>>>>     on Sun, 17 Jan 2010 01:39:21 -0800 writes:

    > On Sat, Jan 16, 2010 at 11:56 PM, Peter Ehlers <ehlers at ucalgary.ca> wrote:
    >> Marius Hofert wrote:
    >>> Dear ExpeRts,
    >>> I have the scatter plot matrix as given below. I would like the different
    >>> "sub-plots" in the scatter plot matrix to be colored differently. How do I
    >>> get all points shown in the upper-left plot (on position (1,1) in the
    >>> scatter plot matrix) to be plotted in blue, and the points shown in the plot
    >>> to the right (on position (1,2) in the scatter plot matrix) to be plotted in
    >>> red? More generally, how can I provide a matrix of colors to be used by
    >>> splom() such that all data points in the corresponding sub-plot of the
    >>> scatter plot matrix are shown in the specified color?
    >>> Cheers,
    >>> Marius
    >>> Here is the code:
    >>> library(lattice)
    >>> entrymat=matrix(0,nrow=3,ncol=3)
    >>> entrymat[1,2]="black"
    >>> entrymat[1,3]="blue"
    >>> entrymat[2,3]="red"
    >>> entrymat=t(entrymat)
    >>> splom(~iris[,1:3],superpanel=function(z,...){
    >>>  mymat.df=data.frame(rows=as.vector(row(entrymat)),cols=as.vector(col(entrymat)),entries=as.vector(entrymat))
    >>>        mymat.df=subset(mymat.df,cols<rows)
    >>>                with(mymat.df,{
    >>>                        panel.text(x=rows,y=cols,labels=entries)
    >>>                })
    >>>  panel.pairs(z,upper.panel=panel.splom,lower.panel=function(...){},...)
    >>>        },varnames=c("1","2","3")
    >>> )
    >> I think that you will have to modify panel.pairs to get what
    >> you want. But I must admit that I can't see why you would
    >> want such a plot. What's achieved by having different
    >> colours in different subpanels? And you would lose the
    >> ability to colour groups differently (or things would become
    >> really complicated and messy).

    > Thanks, I was going to say the same thing, except that it would be
    > conceptually simpler just to add the 'i' and 'j' values as arguments
    > to the "panel" function (the 'pargs' variable). The colors could then
    > be passed through as part of the ... arguments, and the relevant entry
    > extracted in the panel function.
    > The other option is to keep a global counter and increment it inside
    > the panel function, and choosing colors based on that counter and
    > knowledge of the order in which panels are drawn. Not very elegant,
    > but the least intrusive solution I can think of.

    > -Deepayan

Against the R-forge version of lattice,
the following very small patch to  panel.pairs
would allow users to use '(1)' i.e., provide  panel functions
with (i,j) arguments directly.
I'm pretty sure that the change could not easily break existing
splom() usage.

--- R/splom.R	(revision 619)
+++ R/splom.R	(working copy)
@@ -291,7 +291,8 @@
                                    y = z[subscripts, i]),
 ##                                    panel.number = panel.number,
 ##                                    packet.number = packet.number),
-                              list(...))
+                              list(...),
+                              list(i = i, j = j))
                             c(list(x = z[subscripts, j],
                                    y = z[subscripts, i],
@@ -299,7 +300,8 @@
                                    subscripts = subscripts),
 ##                                    panel.number = panel.number,
 ##                                    packet.number = packet.number),
-                              list(...))
+                              list(...),
+                              list(i = i, j = j))
                     if (!("..." %in% names(formals(panel))))
                         pargs <- pargs[intersect(names(pargs), names(formals(panel)))]

With the above change, 
a user could use a panel function with (i,j) arguments, 
and e.g. say

Cmat <- outer(1:6,1:6, 
              function(i,j) rainbow(11, start=.12, end=.5)[i+j-1])

splom(~diag(6), ## for testing: superpanel=mypanel.pairs,
               panel.fill(Cmat[i,j]); panel.splom(x,y,...)
               panel.text(.5,.5, paste("(",i,",",j,")",sep=""))

I think that would allow quite a bit more flexibility without
the need to explicitly "hack"  panel.pairs
(and having to maintain such a hack against the ever-enhancing

Martin Maechler, ETH Zurich

More information about the R-help mailing list