Skip to contents

cube_trend() estimates an ordinary least-squares slope independently for every longitude, latitude, depth, and variable cell of a historical ocean cube. The predictor is actual elapsed time, never observation position.

Usage

cube_trend(
  x,
  method = "linear",
  period = NULL,
  time_unit = "year",
  min_n = 3L,
  diagnostics = FALSE
)

Arguments

x

A valid <ocean_cube> with historical Date or UTC POSIXct time semantics. Memory and lazy NetCDF backends are supported. Recurrent climatology pseudo-time is rejected.

method

The trend method. This must be exactly "linear".

period

NULL for the complete source range, or two ordered bounds defining a closed interval. Bounds must use the same Date or POSIXct semantics as x$time. Partially overlapping bounds are clipped with one warning, and requested and effective periods are retained.

time_unit

Output slope time unit, exactly one of "year", "day", "hour", or "second". A year is exactly 365.2425 days, or 31556952 seconds.

min_n

A finite integer-like scalar of at least two giving the minimum number of finite observations required per cell. The default is three.

diagnostics

A single non-missing logical. If TRUE, aligned n_valid, time_span, intercept, r2, and residual_sd arrays are retained in trend$diagnostics.

Value

An in-memory <ocean_cube> with longitude, latitude, depth, and variable axes preserved and time collapsed to one representational midpoint. data contains the slope in source-unit per selected time unit.

Details

The descriptive linear slope is $$b = \frac{\sum (t_i - \bar{t})(y_i - \bar{y})} {\sum (t_i - \bar{t})^2}.$$ Date differences use exact civil days; POSIXct differences use exact UTC instants and preserve subdaily and fractional-second spacing. Internally, elapsed SI seconds are centered at the output anchor before conversion to the requested public time unit.

Only finite values are fitted. Every finite stored timestamp has one equal observation weight. Irregular spacing is accepted because actual elapsed time is used, but unequal observation density remains scientifically meaningful. Use cube_aggregate_time() first when equal day, month, season, or year weighting is intended.

The singleton output time is the midpoint of the selected stored timestamp range. For Date, half-day ties select the earlier civil day. For POSIXct, the exact arithmetic midpoint instant is retained in UTC. This timestamp is structural; it is not a baseline, breakpoint, or time when the trend occurred.

The core is descriptive only. It does not compute Sen slopes, Mann–Kendall tests, standard errors, confidence intervals, p-values, change metrics, or breakpoints. Lazy NetCDF input is processed in bounded spatial and temporal blocks with one scientific pass; the full source cube is not materialized and the final trend cube is materialized in memory.

Examples

regular_time <- as.Date(c("2000-01-01", "2001-01-01", "2002-01-01"))
regular_years <- (as.numeric(regular_time) - as.numeric(regular_time[1])) / 365.2425
regular <- ocean_cube(
  lon = -80, lat = -12, depth = 0, time = regular_time,
  data = array(4 + regular_years, c(1, 1, 1, 3, 1)),
  vars = "temperature", units = "degC"
)
cube_trend(regular)
#> <ocean_cube>
#>   backend    : memory
#>   source     : <unspecified>
#>   dimensions : 1 x 1 x 1 x 1 x 1 [lon x lat x depth x time x var]
#>   lon        : -80 to -80 (n = 1)
#>   lat        : -12 to -12 (n = 1)
#>   depth      : 0 to 0 (n = 1)
#>   time       : 2000-12-31 to 2000-12-31 (n = 1)
#>   variables  : temperature

time <- as.Date(c("2000-01-01", "2001-01-01", "2004-01-01"))
elapsed_years <- (as.numeric(time) - as.numeric(time[1])) / 365.2425
x <- ocean_cube(
  lon = -80, lat = -12, depth = 0, time = time,
  data = array(5 + 2 * elapsed_years, c(1, 1, 1, 3, 1)),
  vars = "temperature", units = "degC"
)
cube_trend(x)
#> <ocean_cube>
#>   backend    : memory
#>   source     : <unspecified>
#>   dimensions : 1 x 1 x 1 x 1 x 1 [lon x lat x depth x time x var]
#>   lon        : -80 to -80 (n = 1)
#>   lat        : -12 to -12 (n = 1)
#>   depth      : 0 to 0 (n = 1)
#>   time       : 2001-12-31 to 2001-12-31 (n = 1)
#>   variables  : temperature

annual <- suppressWarnings(cube_aggregate_time(x, by = "year"))
cube_trend(annual)
#> <ocean_cube>
#>   backend    : memory
#>   source     : <unspecified>
#>   dimensions : 1 x 1 x 1 x 1 x 1 [lon x lat x depth x time x var]
#>   lon        : -80 to -80 (n = 1)
#>   lat        : -12 to -12 (n = 1)
#>   depth      : 0 to 0 (n = 1)
#>   time       : 2001-12-31 to 2001-12-31 (n = 1)
#>   variables  : temperature

baseline <- suppressWarnings(cube_climatology(x, by = "month"))
anomaly <- cube_anomaly(x, baseline, type = "difference")
cube_trend(anomaly)
#> <ocean_cube>
#>   backend    : memory
#>   source     : <unspecified>
#>   dimensions : 1 x 1 x 1 x 1 x 1 [lon x lat x depth x time x var]
#>   lon        : -80 to -80 (n = 1)
#>   lat        : -12 to -12 (n = 1)
#>   depth      : 0 to 0 (n = 1)
#>   time       : 2001-12-31 to 2001-12-31 (n = 1)
#>   variables  : temperature