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. They are shared by every function in funcs, so statistics needing different arguments have to be requested in separate calls. When group is set, every function in funcs must support grouping.
The stat names its outputs {variable}_{func} — a single function is suffixed too, so a name never depends on how many functions were asked for — and the pipeline then appends the group (when set) and _direc. A funcs: [mean, max] call over hs writes hs_mean_direc and hs_max_direc, exactly the names the equivalent nsector calls produce. Every variable gains a direction coordinate holding the sector-centre values (0°, 45°, …).
The directional variable must be present in the data the call sees, so include it in data_vars when that list is explicit. It is itself reduced by each function, giving dpm_mean_direc and so on.
How sectors are defined¶
For nsector: N the sector width is 360 / N degrees. Sectors are centred on:
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.
The two routes are otherwise interchangeable: they bin the data identically and write identical variable names, so statdir adds no capability of its own — it exists to share one masking of the data and one pass over it between several statistics. Prefer nsector on individual calls unless that matters, or when the statistics need different keyword arguments (which statdir cannot express, since its extra arguments go to every function).
# Equivalent to two separate calls with nsector, but done in one pass:
- func: statdir
dim: time
data_vars: [hs, dpm]
nsector: 16
funcs: [mean, max]
API reference¶
gridstats.ops.directional.statdir(data: xr.Dataset, *, funcs: list[str], dir_var: str = 'dpm', nsector: int = 4, dim: str = 'time', group: str | None = None, **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.
Each delegated statistic returns its result under the name of the variable
it was computed from, so the outputs of two functions would collide on
merge. They are therefore suffixed with the function that produced them:
funcs: [mean, max] over hs yields hs_mean and hs_max. The
suffix is applied for a single function too, so a name never depends on how
many functions were requested.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Dataset
|
Input dataset. Must contain |
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'
|
group
|
str | None
|
Time component for a grouped climatology ( |
None
|
**kwargs
|
Any
|
Forwarded to each stat function. They are shared by every function in funcs; per-function keyword arguments are not supported. |
{}
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with one variable per |
Dataset
|
gaining a 'direction' dimension holding the sector-centre values. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If funcs is empty, if |
Note
This stat adds no capability that the pipeline's own nsector field
does not already provide: func: mean with nsector: 8 produces
exactly the same variable, under exactly the same output name, as
func: statdir with funcs: [mean] and nsector: 8. Its reason
to exist is efficiency — several statistics share one directional
masking of the data and one pass over it, instead of one full pass per
call. Prefer nsector on individual calls unless that matters, or
when the statistics need different keyword arguments.
modal_direction¶
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:
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'
|
group
|
str | None
|
Time component for grouped climatology: |
None
|
weight_var
|
str | None
|
Name of a variable in data to use as histogram weights.
Typical choices: |
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
|
**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.