Description Usage Arguments Details Value Methods Note Author(s) References See Also Examples
Aggregate soil properties along user-defined 'slabs', and optionally within groups.
1 2 3 |
object |
a SoilProfileCollection |
fm |
A formula: either ‘groups ~ var1 + var2 + var3’ where named variables are aggregated within ‘groups’ OR where named variables are aggregated across the entire collection ‘ ~ var1 + var2 + var3’. If 'groups' is a factor it must not contain NA. |
slab.structure |
A user-defined slab thickness (defined by an integer), or user-defined structure (numeric vector). See details below. |
strict |
logical: should horizons be strictly checked for self-consistency? |
slab.fun |
Function used to process each 'slab' of data, ideally returning a vector with names attribute. Defaults to a wrapper function around |
cpm |
Strategy for normalizing slice-wise probabilities, dividing by either: number of profiles with data at the current slice (cpm=1), or by the number of profiles in the collection (cpm=2). Mode 1 values will always sum to the contributing fraction, while mode 2 values will always sum to 1. |
weights |
Column name containing weights. NOT YET IMPLEMENTED |
... |
further arguments passsed to |
Multiple continuous variables OR a single categorical (factor) variable can be aggregated within a call to slab
. Basic error checking is performed to make sure that top and bottom horizon boundaries make sense. User-defined aggregate functions (slab.fun
) should return a named vector of results. A new, named column will appear in the results of slab
for every named element of a vector returned by slab.fun
. See examples below for a simple example of a slab function that computes mean, mean-1SD and mean+1SD. The default slab function wraps hdquantile
from the Hmisc package, which requires at least 2 observations per chunk. Note that if 'group' is a factor it must not contain NAs.
Execution time scales linearly (slower) with the total number of profiles in object
, and exponentially (faster) as the number of profiles / group is increased. slab()
and slice()
are much faster and require less memory if input data are either numeric or character.
There are several possible ways to define slabs, using slab.structure
:
e.g. 10: data are aggregated over a regular sequence of 10-unit thickness slabs
e.g. c(50, 60): data are aggregated over depths spanning 50–60 units
e.g. c(0, 5, 10, 50, 100): data are aggregated over the depths spanning 0–5, 5–10, 10–50, 50–100 units
Output is returned in long format, such that slice-wise aggregates are returned once for each combination of grouping level (optional), variable described in the fm
argument, and depth-wise 'slab'.
Aggregation of numeric variables, using the default slab function:
The names of variables included in the call to slab
.
The name of the grouping variable when provided, otherwise a fake grouping variable named 'all.profiles'.
The slice-wise 5th percentile.
The slice-wise 25th percentile
The slice-wise 50th percentile (median)
The slice-wise 75th percentile
The slice-wise 95th percentile
The slab top boundary.
The slab bottom boundary.
The fraction of profiles contributing to the aggregate value, ranges from 1/n_profiles to 1.
When a single factor variable is used, slice-wise probabilities for each level of that factor are returned as:
The names of variables included in the call to slab
.
The name of the grouping variable when provided, otherwise a fake grouping variable named 'all.profiles'.
The slice-wise probability of level A
The slice-wise probability of level B
The slice-wise probability of level n
The slab top boundary.
The slab bottom boundary.
The fraction of profiles contributing to the aggregate value, ranges from 1/n_profiles to 1.
Typical usage, where input is a SoilProfileCollection
.
Arguments to slab
have changed with aqp
1.5 (2012-12-29) as part of a code clean-up and optimization. Calculation of weighted-summaries was broken in aqp
1.2-6 (2012-06-26), and removed as of aqp
1.5 (2012-12-29). slab
replaced the previously defined soil.slot.multiple
function as of aqp
0.98-8.58 (2011-12-21).
D.E. Beaudette
D.E. Beaudette, P. Roudier, A.T. O'Geen, Algorithms for quantitative pedology: A toolkit for soil scientists, Computers & Geosciences, Volume 52, March 2013, Pages 258-268, 10.1016/j.cageo.2012.10.020.
Harrell FE, Davis CE (1982): A new distribution-free quantile estimator. Biometrika 69:635-640.
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | ##
## basic examples
##
library(lattice)
library(grid)
# load sample data, upgrade to SoilProfileCollection
data(sp1)
depths(sp1) <- id ~ top + bottom
# aggregate entire collection with two different segment sizes
a <- slab(sp1, fm = ~ prop)
b <- slab(sp1, fm = ~ prop, slab.structure=5)
# check output
str(a)
# stack into long format
ab <- make.groups(a, b)
ab$which <- factor(ab$which, levels=c('a','b'),
labels=c('1-cm Interval', '5-cm Interval'))
# plot median and IQR
# custom plotting function for uncertainty viz.
xyplot(top ~ p.q50 | which, data=ab, ylab='Depth',
xlab='median bounded by 25th and 75th percentiles',
lower=ab$p.q25, upper=ab$p.q75, ylim=c(250,-5),
panel=panel.depth_function,
prepanel=prepanel.depth_function,
cf=ab$contributing_fraction,
layout=c(2,1), scales=list(x=list(alternating=1))
)
##
## categorical variable example
##
library(reshape)
# normalize horizon names: result is a factor
sp1$name <- generalize.hz(sp1$name,
new=c('O','A','B','C'),
pat=c('O', '^A','^B','C'))
# compute slice-wise probability so that it sums to contributing fraction, from 0-150
a <- slab(sp1, fm= ~ name, cpm=1, slab.structure=0:150)
# reshape into long format for plotting
a.long <- melt(a, id.vars=c('top','bottom'), measure.vars=c('O','A','B','C'))
# plot horizon type proportions using panels
xyplot(top ~ value | variable, data=a.long, subset=value > 0,
ylim=c(150, -5), type=c('S','g'), horizontal=TRUE, layout=c(4,1), col=1 )
# again, this time using groups
xyplot(top ~ value, data=a.long, groups=variable, subset=value > 0,
ylim=c(150, -5), type=c('S','g'), horizontal=TRUE, asp=2)
# adjust probability to size of collection, from 0-150
a.1 <- slab(sp1, fm= ~ name, cpm=2, slab.structure=0:150)
# reshape into long format for plotting
a.1.long <- melt(a.1, id.vars=c('top','bottom'), measure.vars=c('O','A','B','C'))
# combine aggregation from `cpm` modes 1 and 2
g <- make.groups(cmp.mode.1=a.long, cmp.mode.2=a.1.long)
# plot horizon type proportions
xyplot(top ~ value | variable, groups=which, data=g, subset=value > 0,
ylim=c(240, -5), type=c('S','g'), horizontal=TRUE, layout=c(4,1),
auto.key=list(lines=TRUE, points=FALSE, columns=2),
par.settings=list(superpose.line=list(col=c(1,2))),
scales=list(alternating=3))
# apply slice-wise evaluation of max probability, and assign ML-horizon at each slice
(gen.hz.ml <- get.ml.hz(a, c('O','A','B','C')))
## Not run:
##
## multivariate examples
##
data(sp3)
# add new grouping factor
sp3$group <- 'group 1'
sp3$group[as.numeric(sp3$id) > 5] <- 'group 2'
sp3$group <- factor(sp3$group)
# upgrade to SPC
depths(sp3) <- id ~ top + bottom
site(sp3) <- ~ group
# custom 'slab' function, returning mean +/- 1SD
mean.and.sd <- function(values) {
m <- mean(values, na.rm=TRUE)
s <- sd(values, na.rm=TRUE)
upper <- m + s
lower <- m - s
res <- c(mean=m, lower=lower, upper=upper)
return(res)
}
# aggregate several variables at once, within 'group'
a <- slab(sp3, fm=group ~ L + A + B, slab.fun=mean.and.sd)
# check the results:
# note that 'group' is the column containing group labels
library(lattice)
xyplot(
top ~ mean | variable, data=a, groups=group,
lower=a$lower, upper=a$upper, sync.colors=TRUE, alpha=0.5,
cf=a$contributing_fraction,
ylim=c(125,-5), layout=c(3,1), scales=list(x=list(relation='free')),
par.settings=list(superpose.line=list(lwd=2, col=c('RoyalBlue', 'Orange2'))),
panel=panel.depth_function,
prepanel=prepanel.depth_function,
auto.key=list(columns=2, lines=TRUE, points=FALSE)
)
# compare a single profile to the group-level aggregate values
a.1 <- slab(sp3[1, ], fm=group ~ L + A + B, slab.fun=mean.and.sd)
# manually update the group column
a.1$group <- 'profile 1'
# combine into a single data.frame:
g <- rbind(a, a.1)
# plot with customized line styles
xyplot(
top ~ mean | variable, data=g, groups=group, subscripts=TRUE,
lower=a$lower, upper=a$upper, ylim=c(125,-5),
layout=c(3,1), scales=list(x=list(relation='free')),
panel=panel.depth_function,
prepanel=prepanel.depth_function,
sync.colors=TRUE, alpha=0.25,
par.settings=list(superpose.line=list(col=c('orange', 'royalblue', 'black'),
lwd=2, lty=c(1,1,2))),
auto.key=list(columns=3, lines=TRUE, points=FALSE)
)
## convert mean value for each variable into long format
library(reshape)
# note that depths are no longer in order
a.wide <- cast(a, group + top + bottom ~ variable, value=c('mean'))
## again, this time for a user-defined slab from 40-60 cm
a <- slab(sp3, fm=group ~ L + A + B, slab.structure=c(40,60), slab.fun=mean.and.sd)
# now we have weighted average properties (within the defined slab)
# for each variable, and each group
(a.wide <- cast(a, group + top + bottom ~ variable, value=c('mean')))
## this time, compute the weighted mean of selected properties, by profile ID
a <- slab(sp3, fm= id ~ L + A + B, slab.structure=c(40,60), slab.fun=mean.and.sd)
(a.wide <- cast(a, id + top + bottom ~ variable, value=c('mean')))
## aggregate the entire collection, using default slab function (hdquantile)
## note the missing left-hand side of the formula
a <- slab(sp3, fm= ~ L + A + B)
## weighted-aggregation -- NOT YET IMPLEMENTED --
# load sample data, upgrade to SoilProfileCollection
data(sp1)
depths(sp1) <- id ~ top + bottom
# generate pretend weights as site-level attribute
set.seed(10101)
sp1$site.wts <- runif(n=length(sp1), min=20, max=100)
## End(Not run)
|
This is aqp 1.10
'data.frame': 240 obs. of 10 variables:
$ variable : Factor w/ 1 level "prop": 1 1 1 1 1 1 1 1 1 1 ...
$ all.profiles : num 1 1 1 1 1 1 1 1 1 1 ...
$ p.q5 : num 0.0083 0.0083 0.0332 0.1541 0.1541 ...
$ p.q25 : num 0.474 0.474 0.771 1.552 1.552 ...
$ p.q50 : num 3.44 3.44 3.52 4.53 4.53 ...
$ p.q75 : num 9.52 9.52 8.34 8.51 8.51 ...
$ p.q95 : num 13.7 13.7 16.6 16.6 16.6 ...
$ top : int 0 1 2 3 4 5 6 7 8 9 ...
$ bottom : int 1 2 3 4 5 6 7 8 9 10 ...
$ contributing_fraction: num 1 1 1 1 1 1 1 1 1 1 ...
hz top bottom confidence pseudo.brier
1 O 0 2 37 0.3950617
2 A 2 32 75 0.1547325
3 B 32 145 57 0.3574667
4 C 145 150 71 0.1250000
group top bottom L A B
1 group 1 40 60 45.31202 14.12097 17.68879
2 group 2 40 60 50.04773 6.83886 11.60016
id top bottom L A B
1 1 40 60 48.54910 10.353390 17.306759
2 10 40 60 54.96600 8.650577 14.715420
3 2 40 60 40.15088 13.805446 15.217375
4 3 40 60 43.64350 15.007544 17.511021
5 4 40 60 43.49435 13.704374 16.813956
6 5 40 60 50.72229 17.734101 21.594840
7 6 40 60 52.92916 8.208590 14.901971
8 7 40 60 44.16896 5.113518 8.414187
9 8 40 60 45.74084 5.902099 8.772043
10 9 40 60 52.43369 6.319520 11.197196
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.