# Migrating from climdex.pcic

`climdex.pcic` (Pacific Climate Impacts Consortium) was for many years the standard R implementation of the ETCCDI canonical 27 indices. It was archived from CRAN in 2023. `climatekit` covers the same ETCCDI 27 plus the ET-SCI heatwave family, on a tidy data-frame interface with no compiled code. This vignette walks through what changes when you migrate.

## Function-name crosswalk

Every ETCCDI 27 index in `climdex.pcic` maps to a `climatekit` function. The function names mirror the canonical ETCCDI codes where possible.

ETCCDI code | climdex.pcic | climatekit
--- | --- | ---
FD | `climdex.fd()` | `ck_frost_days()`
ID | `climdex.id()` | `ck_ice_days()`
SU | `climdex.su()` | `ck_summer_days()`
TR | `climdex.tr()` | `ck_tropical_nights()`
TXx | `climdex.txx()` | `ck_txx()`
TNx | `climdex.tnx()` | `ck_tnx()`
TXn | `climdex.txn()` | `ck_txn()`
TNn | `climdex.tnn()` | `ck_tnn()`
TX10p | `climdex.tx10p()` | `ck_tx10p()`
TN10p | `climdex.tn10p()` | `ck_tn10p()`
TX90p | `climdex.tx90p()` | `ck_tx90p()`
TN90p | `climdex.tn90p()` | `ck_tn90p()`
WSDI | `climdex.wsdi()` | `ck_wsdi()`
CSDI | `climdex.csdi()` | `ck_csdi()`
DTR | `climdex.dtr()` | `ck_diurnal_range()`
GSL | `climdex.gsl()` | `ck_growing_season()`
RX1day | `climdex.rx1day()` | `ck_max_1day_precip()`
RX5day | `climdex.rx5day()` | `ck_max_5day_precip()`
SDII | `climdex.sdii()` | `ck_precip_intensity()`
R10mm | `climdex.r10mm()` | `ck_heavy_precip()` (default `threshold = 10`)
R20mm | `climdex.r20mm()` | `ck_very_heavy_precip()` (default `threshold = 20`)
Rnnmm | `climdex.rnnmm(threshold = nn)` | `ck_heavy_precip(threshold = nn)`
CDD | `climdex.cdd()` | `ck_dry_days()`
CWD | `climdex.cwd()` | `ck_wet_days()`
R95p | `climdex.r95p()` / `climdex.r95ptot()` | `ck_r95p()`
R99p | `climdex.r99p()` / `climdex.r99ptot()` | `ck_r99p()`
PRCPTOT | `climdex.prcptot()` | `ck_total_precip()`

Beyond ETCCDI 27, `climatekit` also exposes the ET-SCI heatwave family (`ck_hwn()`, `ck_hwf()`, `ck_hwd()`, `ck_hwm()`, `ck_hwa()`) and the cold-wave duals (`ck_cwn()` etc.), agroclimatic indices (Huglin, Winkler, Branas), drought indices (SPI, SPEI), and comfort indices (heat index, humidex, wind chill).

`ck_etccdi_27()` returns an audit table that maps every ETCCDI code to its `climatekit` function in one place.

## Interface shifts

Inputs. `climdex.pcic` builds a `climdexInput` object from your daily temperature and precipitation series and then runs index functions against that object. `climatekit` takes the daily numeric vectors and a `Date` vector directly. There is no preliminary input object.

    # climdex.pcic
    ci <- climdexInput.raw(
      tmax, tmin, precip, tmax.dates, tmin.dates, prec.dates,
      base.range = c(1961, 1990)
    )
    fd <- climdex.fd(ci)

    # climatekit
    fd <- ck_frost_days(tmin, dates)

Outputs. `climdex.pcic` returns a numeric vector indexed by year (or month). `climatekit` returns a tidy data frame with `period`, `value`, `index`, and `unit` columns:

    ck_frost_days(tmin, dates)
    #> # period       value index        unit
    #> # 2020-01-01      72 frost_days   days
    #> # 2021-01-01      68 frost_days   days
    #> # ...

The tidy shape composes directly with `rbind()`, `ggplot2`, and downstream tabulation. No reshaping needed.

Reference period. The percentile-based indices (`ck_tx10p()`, `ck_tn10p()`, `ck_tx90p()`, `ck_tn90p()`, `ck_r95p()`, `ck_r99p()`, `ck_wsdi()`, `ck_csdi()`, `ck_hwn()` and family) use `ref_start = 1961L`, `ref_end = 1990L` by default. Pass other values to override:

    ck_tx90p(tmax, dates, ref_start = 1981L, ref_end = 2010L)

In-base bootstrap. `climdex.pcic` implements the Zhang et al. (2005) in-base bootstrap to remove the self-inclusion bias for years inside the reference period. `climatekit` does not implement the bootstrap in v0.2.0. Years inside the reference period therefore show a small bias (this is documented in each function’s roxygen). For climate-change attribution work, restrict interpretation to years outside the reference window, or apply the bootstrap externally. Future versions may add it.

Calendar-day window. Both packages use a 5-day window centred on each day of year for percentile estimation, pooled across the reference period.

Spell-counting conventions. Both packages use 6 days minimum for WSDI / CSDI. `climatekit`’s ET-SCI heatwave family uses 3 days minimum (`min_spell = 3L`), matching ET-SCI / `climpact`.

## Sanity-check workflow

When migrating a real station record, sanity-check the new outputs against your previous `climdex.pcic` runs at the annual scale:

    # Old climdex.pcic outputs
    old_fd <- climdex.fd(ci)
    old_txx <- climdex.txx(ci)

    # New climatekit outputs
    new_fd  <- ck_frost_days(tmin, dates)
    new_txx <- ck_txx(tmax, dates)

    # Compare; expect agreement up to NA-handling and base-period self-inclusion
    all.equal(old_fd, new_fd$value)
    all.equal(old_txx, new_txx$value)

Most ETCCDI indices are NA-handling-tolerant by construction. Differences typically come from:

1. Default missing-day handling. `climdex.pcic` has more elaborate rules (e.g. min number of valid days per month) that `climatekit` does not enforce in v0.2.0.
2. In-base bootstrap. As noted above, percentile indices for years 1961-1990 will differ slightly.
3. Calendar leap-day handling. Both packages handle DOY 60 (29 February) without special-casing in v0.2.0.

For all other ETCCDI 27 indices, `climatekit` and `climdex.pcic` should agree to within numerical noise on the same input.

## See also

- `ck_etccdi_27()`: canonical ETCCDI 27 audit table.
- `ck_catalogue()` and `ck_browse()`: full implementation catalogue and filter.
- Alexander, L. V. et al. (2006). Global observed changes in daily climate extremes of temperature and precipitation. Journal of Geophysical Research: Atmospheres, 111(D5). .
- Zhang, X. et al. (2011). Indices for monitoring changes in extremes based on daily temperature and precipitation data. WIREs Climate Change, 2(6), 851-870. .