[Rd] [R] proposal: lattice/levelplot: panel.catlevelplot
Wolfram Fischer - Z/I/M
wolfram@fischer-zim.ch
Tue Jan 21 16:10:09 2003
I suggest to add a panel function to levelplot (or perhaps
to an other 3d lattice function) which is able to translate
the z values into the size of the rectangles.
It could be used to display categorical data.
I append the proposed code and two examples:
- panel.catlevelplot()
- example1.catlevelplot.esoph()
- example2.catlevelplot.esoph()
Wolfram Fischer
#------ CODE --------------------------------------------------------------
panel.catlevelplot <- function (x, y, z, wx, wy, zcol, col.regions, subscripts
, ...
, z.factor.min = 0.02 # factor for z range expansion
# -> little cells become visible
, col.x = NULL # colors for categories in x direction
, col.y = NULL # colors for categories in y direction
, prop.width= TRUE # calculate width of cells proportionally to z position
, prop.height= TRUE # calculate height of cells proportionally to z position
, col.border.cells = NULL # color of borders of levelplot cells
, lwd.border.cells = NULL # linewidth of borders of levelplot cells
){
axis.line <- trellis.par.get('axis.line')
if( is.null( col.border.cells ) ) col.border.cells = axis.line$col
if( is.null( lwd.border.cells ) ) lwd.border.cells = axis.line$lwd
x <- as.numeric( x )
y <- as.numeric( y )
z <- as.numeric( z )
# <--- It would be better to do the following calculations
# of z.x.factor and z.y.factor in the main function (levelplot).
z.min <- min( z, na.rm=TRUE )
z.range <- max( z, na.rm=TRUE ) - z.min
z.factor <- ( z - z.min + z.range * z.factor.min ) /
( z.range * ( 1 + z.factor.min ) )
z.x.factor <- if( prop.width ) z.factor else rep( 1, length(z) )
z.y.factor <- if( prop.height ) z.factor else rep( 1, length(z) )
# --->
fe.grid.rect <- function( sel, fill ){
grid.rect(
x = x[subscripts][sel]
, y = y[subscripts][sel]
, width = wx[subscripts][sel] *
z.x.factor[subscripts][sel]
, height = wy[subscripts][sel] *
z.y.factor[subscripts][sel]
, default.units = "native"
, gp = gpar(
fill = fill
, col = col.border.cells
, lwd = lwd.border.cells
)
)
}
if( any(subscripts) ){
if( ! is.null( col.x ) ){
x.levels <- unique( x )
col.x <- rep( col.x, length = length(x.levels) )
for( i.col in seq( along = x.levels ) ){
fe.grid.rect(
sel = ( x[subscripts] == viq.x.levels[i.col] )
, fill = col.x[i.col]
)
}
}else if( ! is.null( col.y ) ){
y.levels <- unique( y )
col.y <- rep( col.y, length = length(y.levels) )
for( i.col in seq( along = y.levels ) ){
fe.grid.rect(
sel = ( y[subscripts] == y.levels[i.col] )
, fill = col.y[i.col]
)
}
}else{
for( i.col in seq( along = col.regions ) ){
fe.grid.rect(
sel = ( zcol[subscripts] == i.col )
, fill = col.regions[i.col]
)
}
}
}
}
#------ EXAMPLE -----------------------------------------------------------
data(esoph)
library(lattice)
example1.catlevelplot.esoph <- function( ... ){
ncolors <- nlevels( esoph$alcgp )
print( levelplot( ncases ~ agegp * alcgp | tobgp, data=esoph
, main = 'esoph data set'
, sub = 'tobgp'
, cuts = ncolors
, layout = c( 4, 4 )
, scales=list(
x = list( labels = levels( esoph$agegp ), rot=90, alternating=F )
, y = list( labels = levels( esoph$alcgp ) )
)
, panel = panel.catlevelplot
, colorkey = NULL
, col.y = rainbow(ncolors)
# , prop.height = F
, ...
))
}
example2.catlevelplot.esoph <- function( ... ){
cuts <- 15
print( levelplot( ncases ~ agegp * alcgp | tobgp, data=esoph
, main = 'esoph data set'
, sub = 'tobgp'
, cuts = cuts
, layout = c( 4, 4 )
, scales=list(
x = list( labels = levels( esoph$agegp ), rot=90, alternating=F )
, y = list( labels = levels( esoph$alcgp ) )
)
, panel = panel.catlevelplot
, col.regions = rev( heat.colors(cuts+1) )
, col.border.cells = trellis.par.get('background')$col
, lwd.border.cells = 3
, prop.height = F
, prop.width = F
, ...
))
}
#------ -------------------------------------------------------------------