The central conversion verb: takes a table keyed by region code at
geoframe from and returns one keyed at to – a geoframe name of the
same Geoscale, or ANOTHER Geoscale (whose atom layer is the target,
matched on shared atom region keys). Handles both aggregation (fine to
coarse) and disaggregation (coarse to fine) with a single rule per value
column; geoframes that cross-cut work too, because the route always goes
through the atom layer. The route is evaluated as one dplyr pipeline
against the geoscale_map() crosswalk, so x may live in any
supported backend (see below). A crosswalk registered with
register_geoscale_map() short-circuits the derivation.
Usage
recast_geoscale(
x,
gs,
from = NULL,
to,
key = NULL,
values = NULL,
rule = NULL,
weight = NULL,
na_action = c("drop", "error", "keep"),
parent = NULL,
collect = NULL
)Arguments
- x
The data to recast, in any supported backend, with a column named by
keyplus one or more numeric value columns; other columns are preserved as identifiers.- gs
The
Geoscalethe codes inxbelong to.- from
Geoframe name the codes belong to.
NULL(default) is inferred:keywhen it is a geoframe name, else the single geoframe name appearing amongx's columns.- to
Target geoframe name of
gs, or another (named)Geoscale– then the target is that object's atom layer, matched on the atomregionkeys the two objects share.- key
Name of the region-code column in
x. Defaults tofromwhen that column exists, otherwise"region".- values
Character vector of value columns to convert. Default: all numeric columns other than the key and
gs's geoframe columns. Numeric identifiers (e.g.year) must be excluded explicitly.- rule
One of
GEOSCALE_RULES, applied to every value column; orNULL(default) to look each column up withget_geoscale_rule(). A column with neither an explicitrule=nor a registry entry is an ERROR – there is deliberately no fallback (a silently guessed rule is a silent unit error).- weight
Weight column used by
sum(splitting),weighted_meanand the attached shares.NULLuses each column's registered weight, falling back to the object's default weight; when the object declares no weights at all, atoms weigh 1 (an equal split, with a warning when that choice is material, i.e. when disaggregating).- na_action
What to do with atoms that have no code at
fromorto:"drop"(default, with a warning – the affected source share is genuinely lost),"error", or"keep"(retain an explicitNAregion row so totals conserve).- parent
rule = "share"only: the geoframe defining the groups the shares are taken within.NULL(default) usestowhen it differs fromfrom, else the geoframe immediately abovefrom.- collect
For lazy inputs (arrow, dtplyr): materialise the result (
TRUE) or return the uncollected query (default).
Value
The recast table in the input's class, with columns
c(to, identifiers, values): per identifier combination, one row per
member of to (the full target vocabulary, NA where uncovered),
plus an NA region row under na_action = "keep". Identifier column
types are preserved.
Details
Columns of x that are neither the key nor a value column are treated
as identifiers (panel columns – a year, a technology) and preserved as
grouping columns, so panel data recasts correctly in one call; this is
what makes mixed pipelines like
x |> recast_calendar(...) |> recast_geoscale(...) work. Columns named
like gs's geoframes are treated as region attributes and dropped.
The public halves of the route are recast_to_geoatoms() and
recast_from_geoatoms(); recast_geoscale(x, gs, from, to) is
equivalent to
recast_from_geoatoms(recast_to_geoatoms(x, gs, from), gs, to).
Rules (see GEOSCALE_RULES): "sum" splits each source value across its
region's atoms proportionally to the weight before summing up, so totals
are conserved. "weighted_mean" weights by the atom weights; "mean"
is the plain atom-count mean – the two differ exactly when atom weights
differ. "copy" requires a constant value per target region; "sd" is
aggregation-only.
na_action = "keep" emits NA in the output key column. Note that
downstream, energyRt reads NA in a region column as a wildcard
meaning all regions, so "keep" output should not be passed there
unfiltered.
"share" inverts the output contract: the result stays keyed at from,
and each value becomes that region's share of the total over its parent
group (so the shares sum to 1 per parent, per identifier combination).
The parent is parent=, defaulting to to (the reading of
recast_geoscale(x, gs, from = "nuts3", to = "nuts0", rule = "share"):
each nuts3's share within its nuts0); from must nest within it. A
parent group whose total is zero yields NA shares, and an NA value
poisons its group like everywhere else in the package. "share" cannot
be combined with other rules in one call, and weight= is ignored –
the observed values themselves are the weights.
Backends
x may be a data.frame, tibble, data.table, dtplyr lazy table,
or an arrow Dataset/Table/query. The result comes back in the input's
class; lazy inputs (arrow, dtplyr) return the uncollected query unless
collect = TRUE. Lazy results contain the observed target regions
only – the full-vocabulary completion (and its NA rows) applies when
the result is materialised.
Examples
gs <- geoscale_example()
# Extensive quantity, fine -> coarse: totals are preserved
x <- data.frame(atom = c("A1", "A2", "A3", "A4", "A5", "A6"),
capacity = c(1, 2, 3, 4, 5, 6))
recast_geoscale(x, gs, from = "atom", to = "country", rule = "sum")
#> country capacity
#> 1 N 10
#> 2 S 11
# Coarse -> fine: split proportionally to area
y <- data.frame(country = c("N", "S"), capacity = c(10, 20))
recast_geoscale(y, gs, from = "country", to = "state",
rule = "sum", weight = "km2")
#> state capacity
#> 1 N1 3
#> 2 N2 7
#> 3 S1 20
# Intensive quantity: weighted mean going up, copied going down
z <- data.frame(atom = c("A1", "A2", "A3", "A4", "A5", "A6"),
eff = c(0.3, 0.4, 0.5, 0.5, 0.6, 0.6))
recast_geoscale(z, gs, from = "atom", to = "state",
rule = "weighted_mean")
#> state eff
#> 1 N1 0.3666667
#> 2 N2 0.5000000
#> 3 S1 0.6000000
# Share within parent: result stays at the atoms, sums to 1 per country
recast_geoscale(x, gs, from = "atom", to = "country", rule = "share")
#> Warning: 1 unit(s) of `atom` have no code at parent `country` and get NA shares (ROW). Use na_action = "keep" to treat them as one group.
#> atom capacity
#> 1 A1 0.1000000
#> 2 A2 0.2000000
#> 3 A3 0.3000000
#> 4 A4 0.4000000
#> 5 A5 0.4545455
#> 6 A6 0.5454545
#> 7 ROW NA
