ncss-tech / aqp

Algorithms for Quantitative Pedology
http://ncss-tech.github.io/aqp/
54 stars 14 forks source link

plotting method for `slab()` output #97

Open dylanbeaudette opened 5 years ago

dylanbeaudette commented 5 years ago

The current approach to plotting the output from slab() requires considerable work, via lattice or ggplot2. For example:

# plot grouped, aggregate data
xyplot(top ~ p.q50 | variable, groups=taxonname, data=g.slab, ylab='Depth',
             xlab='median bounded by 25th and 75th percentiles',
             lower=g.slab$p.q25, upper=g.slab$p.q75, ylim=c(155,-5),
             panel=panel.depth_function, alpha=0.25, sync.colors=TRUE,
             prepanel=prepanel.depth_function,
             cf=g.slab$contributing_fraction,
       par.strip.text=list(cex=0.8),
             strip=strip.custom(bg=grey(0.85)),
             layout=c(4,1), scales=list(x=list(alternating=1, relation='free'), y=list(alternating=3)),
             par.settings=tps,
             auto.key=list(columns=3, lines=TRUE, points=FALSE)
)

There are several places where the source object (g.slab) is referenced; leaving plenty of opportunity of mistakes upon copy/paste from a manual page.

One possible solution: a bare-bones plotting method (lattice or ggplot2, maybe two functions?) for the standardized output from slab(). Arguments set the y-variable of interest, optional paneling groups, and optional groups symbolized via colors. Additional arguments set upper/lower width via column names, contributing fraction annotation, and adjustments to transparency and syncing of colors. The basic plot object is then modified via update(). There must be a similar strategy for ggplot2 graphics.

Maybe something like this.

# compute depth-slice aggregates by `taxonname`/depth-slice
# for variables: `clay`, `sand`, `pH`
s <- slab(x, taxonname ~ clay + sand + pH, ...)

# top/bottom/variable are known column names
p <- slabPlot(s, 
   stat='p.q50', 
   lower='p.q25', 
   upper='p.q75', 
   groups='taxonname', 
   panel_groups='variable', 
   cf='contributing_fraction', 
   alpha=0.25, 
   sync.colors=TRUE, 
   ...
)

# further customization via `lattice::update()`
p <- update(p, 
             ylab='Depth',
             xlab='median bounded by 25th and 75th percentiles',
             par.strip.text=list(cex=0.8),
             strip=strip.custom(bg=grey(0.85)),
             layout=c(4,1), scales=list(x=list(alternating=1, relation='free'), y=list(alternating=3)),
             par.settings=tps,
             auto.key=list(columns=3, lines=TRUE, points=FALSE)
)
dylanbeaudette commented 3 years ago

This will also require an overhaul of panel.depth_function: there is some lattice magic that needs to be sorted out relative to setting the plot settings. For example, loading the tactile package causes the alpha argument to not be interpreted properly.

The solution for now is to load via ::.

library(aqp)
library(lattice)

## I don't know why, but loading the tactile library messes things up...

s <- lapply(1:100, random_profile, n_prop = 2, method = 'LPP', SPC = TRUE)
s <- combine(s)

site(s)$group <- factor(sample(c('A', 'B'), size = length(s), replace = TRUE))

table(s$group)

a <- slab(s, ~ p1 + p2)

## works

xyplot(
  top ~ p.q50 | variable, data = a,
  lower = a$p.q25, upper = a$p.q75,
  sync.colors = TRUE,
  alpha = 0.5,
  cf = a$contributing_fraction,
  xlab = 'Median Bounded by IQR',
  ylab = 'Depth (cm)',
  ylim = c(125,-5), layout = c(2,1),
  scales = list(x = list(relation = 'free')),
  par.settings = tactile::tactile.theme(superpose.line=list(lwd=2)),
  panel = panel.depth_function,
  prepanel = prepanel.depth_function,
  strip = strip.custom(bg = grey(0.85)),
  auto.key = list(columns = 2, lines = TRUE, points = FALSE)
)

## works

a <- slab(s, group ~ p1 + p2)

tps <- tactile::tactile.theme(superpose.line=list(lwd=2))

xyplot(
  top ~ p.q50 | variable, data = a,
  groups = group,
  lower = a$p.q25, upper = a$p.q75,
  sync.colors = TRUE,
  alpha = 0.2,
  cf = a$contributing_fraction,
  xlab = 'Median Bounded by IQR',
  ylab = 'Depth (cm)',
  ylim = c(125,-5), layout = c(2,1),
  scales = list(x = list(relation = 'free')),
  par.settings = tps,
  panel = panel.depth_function,
  prepanel = prepanel.depth_function,
  strip = strip.custom(bg = grey(0.85)),
  auto.key = list(columns = 2, lines = TRUE, points = FALSE)
)