[R] [lattice] format and rotation of strip text

David Winsemius dwinsemius at comcast.net
Mon Nov 19 06:46:09 CET 2012


On Nov 18, 2012, at 7:05 PM, Tom Roche wrote:

>
> https://stat.ethz.ch/pipermail/r-help/2012-November/329479.html
>>> Hopefully [sufficiently] "small, self-contained example":
>
> mailquotes omitted from "start example" to "end example" to
> ease rerunning the following code:
>
> # start example
> library(reshape2)
> library(lattice)
>
> lon=11
> lat=7
> lev=5
> len=lon*lat*lev
> array.3d <- array(data=c(1:len), dim=c(lat, lon, lev))
>
> # Rewrite the array values "more spatially," i.e., row-wise from
> # bottom left. If there's a more-R-ish way to fill this array as
> # desired, please let me know: I know 'for' loops are deprecated
> # in R.
>
> i=1
> for (z in 1:lev) {
>  for (x in lat:1) {
>    for (y in 1:lon) {
>      array.3d[x,y,z]=i ; i=i+1
>    }
>  }
> }
>
> # produces (with rows=latitudes and cols=longitudes)
> array.3d[,,1]
> array.3d[,,lev]
>
> # convert data=array.3d to dataframe with reshape2::melt
> array.3d.df <- melt(array.3d, varnames=c("lat","lon","lev"),  
> value.name="conc")
> head(array.3d.df)
> tail(array.3d.df)
>
> # make level values {longer, "more realistic"}
>
> array.3d.df$lev <- array.3d.df$lev + 0.12345 # truncated below,  
> and ...
> # ... below note output from these
> head(array.3d.df)
> tail(array.3d.df)
>
> # plot "appropriately" for atmospheric data where lev=pressure: use
> # * lattice::levelplot
> # * one column, since atmospheric levels stack vertically
> # * rev(lev), since layers closer to ground level have higher pressure
> levelplot(
>  conc ~ lon * lat | rev(lev), data=array.3d.df,
>  layout=c(1,lev),  # show levels stacked in 1 vertical column
>  strip=FALSE,      # this suppresses printing strips atop packets
>  strip.left=strip.custom(
>    strip.levels=TRUE,  # print level values
>    strip.names=FALSE   # don't print name of level variable="rev(lev)"
>  )
> )
> # end example
>
>>> Note that the (colored) 'strip' for each panel in the lattice has
>
>>> - the corresponding layer value printed inside curly brackets, e.g.,
>>>  '{1.12345}'
>
>>> - the layer value printed in full
>
>>> - the layer value rotated 90° CCW (like the y-axis label)
>
>>> I would prefer to have
>
>>> + the layer value *not* printed inside curly brackets
>
>>> + the layer value *not* rotated 90° CCW (i.e., to print the layer
>>>  value like the x-axis label)
>
>>> + the layer value truncated or rounded to some significant digits,
>>>  e.g., '1.1'
>
> https://stat.ethz.ch/pipermail/r-help/2012-November/329505.html
>> levelplot(
>>  conc ~ lon * lat | rev(lev), data=array.3d.df,
>>  layout=c(1,lev),   levs=as.character(round(array.3d.df[['lev']],  
>> 1)),
>>  strip=FALSE,
>>  strip.left=strip.custom(
>>    factor.levels=as.character(round(array.3d.df[['lev']], 3)),
>>    strip.levels=TRUE,
>>    horizontal=TRUE,
>>    strip.names=FALSE ,
>>    par.strip.text=list( cex=0.5)
>>  )
>> )
> ...
>> Your example does not do a very good job of testing the levels
>> assignments since they are all the same.
>
> Actually, that claim is false, as can be demonstrated in 2 ways:

Agreed. I was making the erroneous clam on the basis of looking at  
what my code was plotting and at your output of head(array.3d.df) but  
should have printed out the entire vector of as.character(round(array. 
3d.df[['lev']], 1))
>
>
> 1. (simple) Note column=lev in output from
>
> head(array.3d.df)
> tail(array.3d.df)
>
>    The levels are not "all the same."
>
> 2. (more complex, but clearly demonstrates a flaw in the suggestion)
>   Shorten the level values, then comment out the 'factor.levels'
>   argument to strip.custom (above), and plot:
>
> # shorten level values by 2 digits, for bug demonstration
> array.3d.df$lev <- array.3d.df$lev - 0.00045
> # note different output from these in column=lev
> head(array.3d.df)
> tail(array.3d.df)
>
> # comment out for debugging
> levelplot(
>  conc ~ lon * lat | rev(lev), data=array.3d.df, layout=c(1,lev),
>  levs=as.character(round(array.3d.df[['lev']], 1)),
>  strip=FALSE,
>  strip.left=strip.custom(
> #    factor.levels=as.character(round(array.3d.df[['lev']], 3)),
>    strip.levels=TRUE,
>    horizontal=TRUE,
>    strip.names=FALSE ,
>    par.strip.text=list(cex=0.5)
>  )
> )
>
>   Note that,
>
> -  without the line above commented out, strip values are (correctly)
>   all 1.123

I'm very puzzled here. Why should they all be the same? I thought you  
were asking why they shouldn't be different.

>
> +  with the line above commented out, strip values are (correctly)
>   1.123 .. 5.123
>

I get blank strips (or rather only side strips with red bars that  
indicate progression.

> Am I missing something? If not, how to round() or signif() the values
> obtained from array.3d.df$lev and displayed in the strips?

I showed how they should be rounded but maybe they needed to be  
indexed or have unique put around them so they cam be displayed in the  
proper sequence. This seems to be a better result:

levelplot(
  conc ~ lon * lat | rev(lev), data=array.3d.df, layout=c(1,lev),
  levs=as.character(round(array.3d.df[['lev']], 1)),
  strip=FALSE,
  strip.left=strip.custom(
factor.levels=as.character(round(unique(array.3d.df[['lev']]), 2)),
    strip.levels=TRUE,
    horizontal=TRUE,
    strip.names=FALSE ,
    par.strip.text=list(cex=0.5)
  )
)


David Winsemius, MD
Alameda, CA, USA




More information about the R-help mailing list