Skip to content

Directional Statistics

Apply one or more stat functions over equal-width directional sectors.


statdir

Bins the dataset by direction, applies each listed function to each sector, and concatenates the results along a new direction dimension.

Parameter Type Default Description
funcs list[str] Names of registered stat functions to apply per sector (e.g. [mean, max]).
dir_var str "dpm" Variable name used for directional binning. Must be in the dataset.
nsector int 4 Number of equally-spaced sectors. 8 → 45° sectors, 16 → 22.5°, etc.

Additional keyword arguments (e.g. group) are forwarded to each stat function.

Output variables are named as {variable}_{func} and gain a direction coordinate with sector-centre values (0°, 45°, …).

- func: statdir
  dim: time
  data_vars: [hs, tp]
  dir_var: dpm
  nsector: 8
  funcs: [mean, max]

How sectors are defined

For nsector: N the sector width is 360 / N degrees. Sectors are centred on:

0°, 360/N°, 2×360/N°, …

Each sector is a half-open interval [centre − width/2, centre + width/2). The wrap-around sector (centred on 0°) correctly handles the 0°/360° boundary.

Data points outside a sector are set to NaN before the stat function is called, so all registered functions work transparently without modification.


Difference from nsector on individual calls

Setting nsector on a regular call (e.g. func: mean, nsector: 8) is handled at the pipeline level and applies a single function. statdir lets you apply multiple functions in one pass while keeping the same directional binning, which is more efficient when you need several statistics per sector.

# Equivalent to two separate calls with nsector, but done in one pass:
- func: statdir
  dim: time
  data_vars: [hs]
  nsector: 16
  funcs: [mean, max, quantile]
  q: [0.90, 0.99]

API reference

gridstats.ops.directional.statdir(data: xr.Dataset, *, funcs: list[str], dir_var: str = 'dpm', nsector: int = 4, dim: str = 'time', **kwargs: Any) -> xr.Dataset

Apply multiple stat functions over directional sectors.

Bins the dataset by nsector equal directional sectors, applies each function in funcs to each sector, then concatenates results along a new 'direction' dimension.

Parameters:

Name Type Description Default
data Dataset

Input dataset. Must contain dir_var.

required
funcs list[str]

Names of registered stat functions to apply per sector.

required
dir_var str

Name of the directional variable used for binning.

'dpm'
nsector int

Number of equally-spaced directional sectors (default 4).

4
dim str

Time dimension name.

'time'
**kwargs Any

Forwarded to each stat function.

{}

Returns:

Type Description
Dataset

Dataset with a 'direction' dimension containing sector-centre values.


Per-cell modal (most frequent) direction from a weighted circular histogram. Uses a histogram-based mode rather than a vector mean, making it robust to bimodal and anti-parallel direction distributions (e.g. monsoon reversals where the arithmetic mean of 90° and 270° is meaningless).

All direction variables in data_vars are processed; the optional weight_var is excluded from output but used to weight the histogram.

Parameter Type Default Description
weight_var str | None None Variable name for histogram weights. None = unweighted frequency.
bin_width_deg float 10.0 Histogram bin width (degrees). Must divide 360 evenly.
smooth bool True Apply 3-bin circular moving average before taking the mode, stabilising against single-bin noise.
- func: modal_direction
  dim: time
  data_vars: [dpm, dp_sea, dp_sw1]
  weight_var: hs           # weight by wave energy
  bin_width_deg: 10.0
  smooth: true

With monthly grouping:

- func: modal_direction
  dim: time
  group: month
  data_vars: [dpm]
  weight_var: hs

Note

apply_ufunc with allow_rechunk=True handles the single-chunk requirement along dim automatically in the dask graph — no manual rechunking needed before calling this stat.

API reference

gridstats.ops.directional.modal_direction(data: xr.Dataset, *, dim: str = 'time', group: str | None = None, weight_var: str | None = None, bin_width_deg: float = 10.0, smooth: bool = True, **kwargs: Any) -> xr.Dataset

Per-cell modal (most frequent) direction from a weighted circular histogram.

Uses a histogram-based mode rather than a vector mean, so it is robust to bimodal and anti-parallel direction distributions (e.g. monsoon reversals where the arithmetic mean of 90° and 270° is meaningless).

Parameters:

Name Type Description Default
data Dataset

Input dataset. Direction variables must be in degrees in [0, 360).

required
dim str

Dimension to reduce along (default 'time').

'time'
group str | None

Time component for grouped climatology: 'month', 'season', or 'year'. When set, the output gains a dimension named after the group (e.g. a 'month' dimension with values 1–12).

None
weight_var str | None

Name of a variable in data to use as histogram weights. Typical choices: 'hs' for occurrence, 'hs'**2 for energy, 'hs'**2 * 'te' for energy flux. When None each sample contributes equally (unweighted frequency histogram).

None
bin_width_deg float

Histogram bin width in degrees. Must divide 360 evenly. 10° (36 bins) is a good default; use 5° for sharper modes on long records.

10.0
smooth bool

If True (default), apply a 3-bin circular moving average to the histogram before taking the argmax, stabilising the mode against single-bin noise.

True
**kwargs Any

Accepted but not forwarded (pipeline compatibility).

{}

Returns:

Type Description
Dataset

Dataset with one variable per direction variable in data (excluding

Dataset

weight_var). Each variable holds the centre of the dominant histogram

Dataset

bin at every grid cell. Gains a group dimension when group is set.

Note

apply_ufunc with allow_rechunk=True handles the single-chunk requirement along dim automatically in the dask graph, so manual rechunking is not needed before calling this stat.