Statistics & indices¶
Descriptive statistics, agreement measures, sample-depth signal strength, and derived indices.
stats¶
Summary statistics for each series in a ring-width dataset.
Reports, for each series, the columns 'first', 'last', 'year', 'mean', 'median', 'stdev', 'skew', 'kurtosis', 'gini', and 'ar1'.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inp
|
str or pandas dataframe
|
a data file (.CSV or .RWL) or a pandas dataframe imported from dpl.readers(). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
data |
pandas dataframe
|
|
Examples:
References
.. [1] https:/opendendro.org/dplpy-man/#stats
samp_stats¶
Per-year sample-tracking statistics for a ring-width dataset.
For every year in the dataset this reports how many series are present and,
across just those present series, their mean length and mean cambial age --
the num / seg / age columns of an ARSTAN "tabs" file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
pandas dataframe
|
ring widths, years as the index and series as columns (e.g. from dpl.readers()). Raw widths or detrended indices give the same result -- only the pattern of present/absent values is used. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
out |
pandas dataframe indexed by year with columns
|
Years with no series present get |
Notes
seg counts a series' measured rings; age counts years since its first
ring. The two differ only for a series with an interior gap (an unmeasured
year inside its span), for which the tree still ages but the ring is not
counted.
Examples:
rwi_stats¶
Whole-record chronology signal statistics (rbar, EPS, SNR).
Computes the mean interseries correlation (rbar), expressed population signal (EPS), and signal-to-noise ratio (SNR) over the entire record as a single-row summary. The non-running counterpart of rwi_stats_running(), which it calls with running_window=False; see that function for full parameter and statistic descriptions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwi_data
|
pandas dataframe
|
detrended ring-width indices (e.g. from dpl.detrend()). |
required |
ids
|
dict, pandas dataframe, or None
|
tree/core structure; see rwi_stats_running(). |
None
|
period
|
str
|
"max" (pairwise-complete overlaps) or "common" (complete rows only). |
"max"
|
corr
|
str
|
correlation type, "Spearman" or "Pearson". |
"Spearman"
|
prewhiten
|
boolean
|
prewhiten each series with an AR model before computing correlations. |
False
|
min_corr_overlap
|
int or None
|
minimum number of overlapping years for a series pair to contribute. |
None
|
zero_is_missing
|
boolean
|
treat exact zeros as missing values. |
True
|
round_decimals
|
int or None
|
decimal places to round the statistic columns to. |
3
|
Returns:
| Name | Type | Description |
|---|---|---|
result |
a one-row pandas dataframe of chronology signal statistics.
|
|
Examples:
>>> import dplpy as dpl
>>> rwi = dpl.detrend(dpl.readers("../tests/data/csv/file.csv"), plot=False)
>>> dpl.rwi_stats(rwi)
References
.. [1] https://rdrr.io/cran/dplR/man/rwi.stats.running.html .. [2] Wigley, Briffa & Jones (1984), J. Climate Appl. Meteor., 23, 201-213.
rwi_stats_running¶
Running (moving-window) chronology signal statistics (rbar, EPS, SNR).
For each moving window along the chronology, computes the mean interseries correlation (rbar) and, from it, the expressed population signal (EPS) and signal-to-noise ratio (SNR) of Wigley et al. (1984). Port of dplR's rwi.stats.running(); rwi_stats() is the whole-record special case (running_window=False).
When tree/core IDs are supplied (see ids), correlations are split into
within-tree (rbar_wt) and between-tree (rbar_bt) components, and the effective
signal rbar_eff accounts for averaging multiple cores per tree (via an effective
cores-per-tree factor c_eff). Without IDs, every series is its own tree and
rbar_eff == rbar_bt == rbar_tot.
EPS = n * rbar_eff / ((n - 1) * rbar_eff + 1) and SNR = n * rbar_eff / (1 - rbar_eff), where n is the number of trees contributing to the between-tree correlations.
NOTE: no acceptance threshold (e.g. the frequently cited EPS > 0.85) is applied or implied here; that threshold was an illustrative example for SSS (see dpl.sss()), not a general criterion for EPS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwi_data
|
pandas dataframe
|
detrended ring-width indices (e.g. from dpl.detrend()), with years as the index and series as columns. |
required |
ids
|
dict, pandas dataframe, or None
|
tree/core structure used to split within- vs between-tree correlations. Either a dict mapping {series_name: tree_id}, a dataframe with a 'tree' column indexed by series name (such as produced by dpl.read_ids()), or None to treat every series as its own tree (one core per tree). |
None
|
period
|
str
|
"max" uses each pair's own overlapping years (pairwise-complete); "common" restricts each window to years present in every series. |
"max"
|
corr
|
str
|
correlation type, "Spearman" or "Pearson". |
"Spearman"
|
prewhiten
|
boolean
|
prewhiten each series with an AR model before computing correlations. |
False
|
running_window
|
boolean
|
if False, a single window spanning the whole record is used (this is what rwi_stats() invokes). |
True
|
window_length
|
int or None
|
length of each moving window in years; defaults to min(50, n_years). |
None
|
window_overlap
|
int or None
|
number of years successive windows overlap; defaults to window_length // 2. |
None
|
min_corr_overlap
|
int or None
|
minimum number of overlapping years required for a series pair to contribute a correlation; defaults to min(30, window_length). |
None
|
zero_is_missing
|
boolean
|
treat exact zeros as missing values (a zero RWI is treated as absent). |
True
|
round_decimals
|
int or None
|
decimal places to round the real-valued statistic columns to; None leaves them unrounded. |
3
|
common_interval
|
str, (int, int), or None
|
restrict the data to a common interval before computing statistics. 'series', 'years' or 'both' selects a complete overlap-only rectangle via dpl.common_interval() (maximising cores, years, or cells); a (start_year, end_year) pair restricts to that inclusive span. None (default) uses the full record. Recommended for unevenly-distributed data, where period='common' on the full record can be empty. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
result |
pandas dataframe with one row per window (or a single row if
|
running_window=False). Columns: start_year, mid_year, end_year (running only), n_cores, n_trees, n, n_tot, n_wt, n_bt, rbar_tot, rbar_wt, rbar_bt, c_eff, rbar_eff, eps, snr. |
Examples:
>>> import dplpy as dpl
>>> rwi = dpl.detrend(dpl.readers("../tests/data/csv/file.csv"), plot=False)
>>> dpl.rwi_stats_running(rwi, window_length=60, window_overlap=30)
References
.. [1] https://rdrr.io/cran/dplR/man/rwi.stats.running.html .. [2] Wigley, Briffa & Jones (1984), J. Climate Appl. Meteor., 23, 201-213. .. [3] Buras (2017), Dendrochronologia, 44, 130-132.
sens1¶
Mean sensitivity (dplR sens1).
The standard measure of year-to-year variability in dendrochronology (Douglass;
Eq. 1 of Biondi and Qeadan 2008), typically computed on detrended series. For a
single series of n (non-missing) values,
sens1 = (2 / (n - 1)) * sum_i |x_i - x_{i-1}| / (x_i + x_{i-1})
where a 0/0 term from an x_i + x_{i-1} == 0 pair is skipped while
n - 1 is unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
pandas.DataFrame, pandas.Series, 1-D array-like, or str
|
A ring-width dataset (years x series), a single series, or a path/URL to a .csv/.rwl file. NA/NaN values are dropped before the calculation. |
required |
Returns:
| Type | Description |
|---|---|
float or Series
|
For a single series, the scalar mean sensitivity. For a DataFrame (or a file
path, which is read into one), a Series of the statistic indexed by series
name. A series with fewer than two values yields |
Examples:
References
.. [1] Biondi, F. and Qeadan, F. (2008) Inequality in paleorecords. Ecology 89, 1056-1067. .. [2] https:/opendendro.org/dplpy-man/#sens1
sens2¶
Mean sensitivity for a series with a trend (dplR sens2).
Eq. 2 of Biondi and Qeadan (2008): the local two-year denominator of
:func:sens1 is replaced by the series mean, so a growth trend does not
inflate the statistic. For a single series of n (non-missing) values,
sens2 = sum_i |x_{i+1} - x_i| / (sum(x) - sum(x)/n)
= sum_i |x_{i+1} - x_i| / ((n - 1) * mean(x))
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
pandas.DataFrame, pandas.Series, 1-D array-like, or str
|
A ring-width dataset (years x series), a single series, or a path/URL to a .csv/.rwl file. NA/NaN values are dropped before the calculation. |
required |
Returns:
| Type | Description |
|---|---|
float or Series
|
A scalar for a single series, or a Series indexed by series name for a
DataFrame / file path. Fewer than two values yields |
Examples:
References
.. [1] Biondi, F. and Qeadan, F. (2008) Inequality in paleorecords. Ecology 89, 1056-1067. .. [2] https:/opendendro.org/dplpy-man/#sens2
glk¶
Gleichlaeufigkeit (sign-agreement) between all pairs of series.
For every pair of series this is the proportion of shared intervals in which
the two move in the same direction, counting a flat (no-change) interval as
half agreement. A port of dplR's glk (Visser's implementation).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame or str
|
A ring-width dataset (years x series), or a path/URL to a .csv/.rwl file. |
required |
overlap
|
int
|
Minimum number of overlapping growth-change intervals a pair must share; pairs below this are NaN. Must be a single integer >= 3. A warning is issued for values below 50 (matches likely become statistically insignificant). |
50
|
prob
|
bool
|
If True, also return a matrix of two-sided p-values. |
True
|
Returns:
| Type | Description |
|---|---|
dict of pandas.DataFrame
|
|
See Also
sgc : the synchronous / semi-synchronous decomposition (glk = sgc + ssgc/2).
Examples:
References
.. [1] Schweingruber, F.H. (1988) Tree Rings. Kluwer. .. [2] Visser, R.M. (2021) On the similarity of tree-ring patterns: Journal of Archaeological Science 125. .. [3] https:/opendendro.org/dplpy-man/#glk
sgc¶
Synchronous and semi-synchronous growth changes between all pairs.
A decomposition of :func:glk: sgc is the proportion of shared intervals
in which two series move in the same direction, and ssgc the proportion
in which exactly one is flat. A port of dplR's sgc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
DataFrame or str
|
A ring-width dataset (years x series), or a path/URL to a .csv/.rwl file. |
required |
overlap
|
int
|
Minimum overlapping intervals per pair (a single integer >= 3); pairs below this are NaN. A warning is issued below 50. |
50
|
prob
|
bool
|
If True, also return a matrix of two-sided p-values (computed from sgc). |
True
|
Returns:
| Type | Description |
|---|---|
dict of pandas.DataFrame
|
|
See Also
glk : the combined statistic, glk = sgc + ssgc/2.
Examples:
References
.. [1] Visser, R.M. (2021) On the similarity of tree-ring patterns: Journal of Archaeological Science 125. .. [2] https:/opendendro.org/dplpy-man/#sgc
sss¶
Subsample signal strength (SSS) as a per-year series.
For each year, computes how well the subsample of series present that year represents the full N-series chronology (Wigley et al. 1984):
SSS(t) = n(t) * (1 + (N - 1) * rbar) / (N * (1 + (n(t) - 1) * rbar))
where N is the total number of trees in the record, rbar is the effective mean interseries correlation (both fixed, from a whole-record dpl.rwi_stats() call), and n(t) is the number of trees (or cores, if no tree IDs are given) present in year t. Mirrors dplR's sss(), holding rbar and N constant while only the per-year sample depth varies -- distinct from the running EPS of dpl.rwi_stats_running(), which recomputes rbar in each window.
No acceptance threshold is applied; SSS is the statistic Wigley et al. (1984) intended for assessing declining reconstruction skill back in time (the frequently cited 0.85 value was an illustrative example, not a rule).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwi_data
|
pandas dataframe
|
detrended ring-width indices (e.g. from dpl.detrend()), years as index and series as columns. |
required |
ids
|
dict, pandas dataframe, or None
|
tree/core structure (see dpl.rwi_stats() / dpl.read_ids()). When given, both N and the per-year sample depth are counted in trees; when None, every series is its own tree and they are counted in cores. |
None
|
corr
|
str
|
correlation type used for the underlying rbar ("Spearman" or "Pearson"). |
"Spearman"
|
zero_is_missing
|
boolean
|
treat exact zeros as missing (applied consistently to the rbar calculation and the per-year sample-depth count). |
True
|
common_interval
|
str, (int, int), or None
|
restrict to a common interval before computing SSS: 'series', 'years' or 'both' selects one via dpl.common_interval(), and a (start_year, end_year) pair restricts to that span. rbar, N, n(t) and the returned years are then all taken from that trimmed block. None (default) uses the full record. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
result |
pandas Series named "sss", indexed by year, with the per-year subsample
|
signal strength (over the common interval if one was chosen). |
Examples:
>>> import dplpy as dpl
>>> rwi = dpl.detrend(dpl.readers("../tests/data/csv/file.csv"), plot=False)
>>> dpl.sss(rwi)
References
.. [1] https://rdrr.io/cran/dplR/man/sss.html .. [2] Wigley, Briffa & Jones (1984), J. Climate Appl. Meteor., 23, 201-213. .. [3] Buras (2017), Dendrochronologia, 44, 130-132.
tree_mean¶
Average each tree's cores into a single tree-level series (dplR treeMean).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
A ring-width dataset (years x cores/series). |
required |
ids
|
DataFrame or dict
|
The tree/core structure that says which tree each series belongs to --
the output of :func: |
required |
na_rm
|
bool
|
If False (dplR's default), a tree's value for a year is NaN unless every one of its cores has a measurement that year. If True, the mean is taken over whatever cores are present (a year is NaN only when the tree has no core at all that year). |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
A ring-width dataset (years x trees). Columns are the unique tree IDs, in
order of first appearance among the input columns; the year index is
preserved. Feed it straight to :func: |
Examples:
>>> ids = dpl.read_ids(data)
>>> dpl.tree_mean(data, ids)
>>> dpl.chron(dpl.tree_mean(dpl.detrend(data), ids, na_rm=True))
References
.. [1] https:/opendendro.org/dplpy-man/#tree_mean
common_interval¶
Select a complete common interval from a set of ring-width series.
Finds the largest block of years and series in which every retained series has a
value for every retained year (a complete, gap-free rectangle) -- the interval
over which chronology statistics such as rbar, EPS and SSS can be computed
without missing values. Ported from dplR's common.interval().
Three strategies trade off the number of series against the number of years:
"series"maximises the number of series (cores) at the highest sample depth -- typically a short, deep interval."years"maximises the number of years, dropping short series to extend the span -- typically a long, shallow interval."both"(default) maximises the number of data cells (series x years), a balance of the two.
To use an interval of your own choosing, slice the frame (e.g.
rwi.loc[1800:1980]) before passing it on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series (raw or detrended), years as the index, series as columns. |
required |
type
|
(series, years, both)
|
the selection strategy described above. |
"series"
|
plot
|
bool
|
if True, draw a coverage diagram (each series as a grey span, with the retained common interval overlaid in black). |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
the trimmed frame containing only the retained series and years (a complete rectangle). The full frame is returned unchanged if no trimming is possible/needed. |
Examples:
>>> import dplpy as dpl
>>> rwi = dpl.detrend(dpl.readers("../tests/data/csv/co021.csv"), plot=False)
>>> ci = dpl.common_interval(rwi, type="both")
>>> dpl.rwi_stats(ci)
References
.. [1] https://rdrr.io/cran/dplR/man/common.interval.html .. [2] Bunn (2008), Dendrochronologia, 26, 115-124.
bai_out¶
Basal area increment computed from the outside in (dplR bai.out).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
Year-indexed ring widths (one column per series). |
required |
diam
|
DataFrame, dict, or pandas.Series
|
Stem diameter for each series, in the same length units as the ring
widths. A DataFrame uses a |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
BAI in squared length units, same shape/index as |
bai_in¶
Basal area increment computed from the pith out (dplR bai.in).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
Year-indexed ring widths (one column per series). |
required |
d2pith
|
DataFrame, dict, or pandas.Series
|
Distance from the innermost measured ring to the pith, per series, in the
same length units as the ring widths. A DataFrame uses a |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
BAI in squared length units, same shape/index as |