Skip to content

BootSample

Description

BootSample returns a bootstrap sample of the input values. A bootstrap sample is a resampling (“sample with replacement”) version of collected data. The idea is that repeated bootstrap re-samples of one dataset will reproduce sampling variability; the distribution of statistics of repeated bootstrap samples (ideally) is a good approximation for the distribution you would obtain if you repeatedly sampled the source population directly.

Smoothing is possible if the input data is univariate. This is functionally the same as sampling a KDE created from the original sample. Smoothing is important for statistics that exhibit “lumpiness” with an unsmoothed bootstrap; the median and other order-based statistics like IQR are textbook examples.

BootSample is mostly a helper function that is called by all the other bootstrap-related lambda functions; it would not normally be called on its own (other than to illustrate the nature of bootstrapping, as in the example below).

Syntax

BootSample(sample, [bw = 0]) where

  • sample is the input data that is to be resampled. If the input is univariate (row or column variable) the items are resampled with replacement and the output is a column vector. If the input is a matrix, the data is resampled by row so that a row’s items (assumed to be a single observation) are kept together.
  • bw is the smoothing parameter. The default bw = 0 means no smoothing occurs; with bw = 1 you are sampling from a KDE of the sample created with the Silverman-recommended bandwidth. This parameter is ignored if sample is multivariate.

BootSample returns a bootstrap sample the same size as the input. A vector input is returned as a column vector, after blank cells are dropped; other non-numeric values are resampled the same as numeric values. A matrix input is returned as a matrix of the same shape.

​This function is volatile (and, by extension, so are all bootstrap functions that depend on it).

Example

In the example below, the input sample is simply the series 1...101...10. Obviously this is not a realistic data sample but it illustrates the nature of bootstrap samples. Five unsmoothed bootstrap samples are shown, each one of which is the same size (N=10N = 10) as the original and is created by sampling with replacement. Note that some numbers are omitted and some appear multiple times.

Five smoothed bootstraps are also shown (with bw = 1). This can be viewed as adding a little bit of noise to each value re-sampled from the original sample. There are no repeats here.

A sample of 10 values beside 5 unsmoothed bootstrap samples (with repeats) and 5 smoothed ones (no repeats)

The Excel file is below. Since BootSample is volatile, the numbers you see will not match mine exactly.

Download: BootSample.xlsx

Source Code

Helpers used: BootObs

BootSample has a dependency, BootObs (linked above).

BootSample = LAMBDA(
    sample,
    [bw],  // smoothing bandwidth, same as KDE's bw (default 0, unsmoothed). Ignored for matrix input.
    LET(
        X, BootObs(sample),      // matrix as-is (rows = observations), or a flattened column vector
        n, ROWS(X),
        draw, CHOOSEROWS(X, RANDARRAY(n, 1, 1, n, TRUE)),
        // matrix input (more than one column): whole rows resampled above, no smoothing support
        matrixResult, draw,
        // vector input: optionally apply the smoothed-bootstrap correction
        vectorResult, LET(
            bw, IF(ISOMITTED(bw), 0, bw),
            s, STDEV.S(X),
            // only evaluated (LET is lazy) when bw<>0 and s<>0, per the final IF below
            smoothedResult, LET(
                H, 1.059 * MIN(s, IQR(X, TRUE)) * n ^ (-0.2),
                W, H * bw,
                Xbar, AVERAGE(X),
                Z, NORM.INV(RANDARRAY(n, 1), 0, 1),
                // variance-corrected smoothed bootstrap (Silverman & Young):
                // shrink back toward Xbar so Var(result) still matches Var(X)
                Xbar + (draw + W * Z - Xbar) / SQRT(1 + (W / s) ^ 2)
            ),
            // a zero-variance sample has nothing to smooth; fall back to the plain draw
            IF(OR(bw = 0, s = 0), draw, smoothedResult)
        ),
        IF(COLUMNS(X) = 1, vectorResult, matrixResult)
    )
);