Skip to content

cd_anomaly() and cd_summary(): accept series outside cd_variables() instead of returning NA #92

Closed

Description

@NewGraphEnvironment

If we do it: cd's baseline, anomaly, trend and window-comparison functions work on any annual series in cd's long format, streamflow or stream temperature produced by another package included. Departure is then computed one way everywhere. If we never do: a package that wants departure for its own series either gets NA from cd_anomaly() or writes a second copy of the statistics.

Problem

cd_baseline(), cd_trend() and cd_compare() already accept any tibble with variable, period, year, value. cd_anomaly() does not: it looks the anomaly type up in cd_variables(), and a variable that is not there returns NA without an error.

x <- data.frame(variable = "q_mean", period = "spawn", year = 2000:2001, value = 1:2)
cd_anomaly(x, cd_baseline(x, 2000:2001))
#>   variable period year anomaly anomaly_type unit
#> 1   q_mean  spawn 2000      NA         <NA> <NA>
#> 2   q_mean  spawn 2001      NA         <NA> <NA>

cd_summary() uses the same lookup for labels and units.

Proposed Solution

  • cd_anomaly(): when the input carries anomaly_type (and optionally unit) columns, use them; otherwise fall back to cd_variables(). Raise an error naming any variable whose type cannot be resolved, instead of returning NA.
  • cd_summary(): the same fallback for long_name and unit.
  • Tests on a series that is not in cd_variables(), and a documented input contract (variable, period, year, value, optional anomaly_type/unit) so other packages can target it.
  • period is free text in the consumer functions; confirm nothing downstream assumes cd_periods() values.

Scope stays with the statistics. Building per-year values from a daily series over date windows belongs to whichever package produces the series.

What landed (#94)

The work settled three points the proposal left open, and grew one guard:

  • unit is the anomaly's unit, passed through verbatim — the same meaning cd_variables()$unit already had (prcp is "%"). A registered variable that carries a different anomaly_type from the registry's (e.g. prcp as "absolute") gets no registry unit.
  • cd_trend() passes the metadata through — long_name always, anomaly_type/unit only when it trends the anomaly column — so cd_summary() sees it without the caller joining anything. The proposal's "same fallback in cd_summary()" could not work on its own, because cd_trend() dropped every input column.
  • cd_summary() falls back to the variable name for the label, with no unit, rather than erroring: a label is cosmetic.
  • Added: one row per (variable, period, year) is enforced in cd_baseline, cd_anomaly, cd_compare and cd_trend. Two stations stacked under one variable used to be pooled silently; they are now refused. Grouped input is accepted.
  • period audit: nothing downstream assumes cd_periods() values.

The contract is under "Input contract" in ?cd_anomaly. Plot labels are split out to #93.

Activity

  1. added a commit that references this issue on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions