frametoLme(): residual series in
$fluc could be attached to the wrong rows, because row
labels were used as row positions when the residual frame was built.
Residuals are now matched to model-data rows by label, and fitting stops
with an error if any row cannot be matched. Model fits were not
affected. The defect was introduced in development versions 0.9.2-0.9.4
(April 2026); the CRAN release 0.9.1 matched rows with merge(…, by =
‘row.names’) and is not affected.$fluc.wlai(): with label_year = "end",
hydrological years were still labeled by the year in which they start,
so October 2000 to September 2001 came out as 2000 instead of 2001 and
lag 0 pointed to the year before ring formation. The output now has a
year column: with "end" it is the year in
which each hydrological year ends, with "start" the year in
which it starts. hydro_year_id keeps its meaning and is
always the start year. label_year now also applies when the
input already has a hydro_year_id column, as returned by
moveYr(); if the input year column follows the
other convention, wlai() warns and its own
label_year decides. With calendar years
label_year has no effect. label_year was added
in development version 0.9.2; the CRAN release 0.9.1 is not
affected.frametoLme(): when the input had more than one
time column (for example year and the time
column added by rtimes()) and the model used one other than
the first detected, building $fluc stopped with “object
‘year’ not found”. $fluc is now built on the time variable
of the fitted fixed formula. Fits that use year are
unchanged. The code that picked the first detected time column was
introduced in development version 0.9.2; versions 0.9 and 0.9.1 built
$fluc differently.shiftFrame(): dot-separated wide column names
were read in the wrong order, so P16106.17.a gave
plot = a and sample = P16106, and climate
columns such as P16106.Apr gave plot = Apr and
month = P16106. Column names are read from the highest
level to the lowest again, as in 0.9.1: P16106.17.a is core
a of tree 17 in plot P16106. This
also corrects modelFrame() on wide chronologies, which
fitted the grouping structure on the swapped labels (for
Pchron, 8 trees instead of 4). The defect was introduced in
development version 0.9.2; the CRAN release 0.9.1 is not affected.moveYr() then wlai() route
through ringApply(): the start month recorded by
moveYr() was lost when ringApply() combined
the blocks, so wlai() ordered each hydrological year
January to December instead of October to September and returned
different aridity indexes (for PTclim05, P44005, October
1998 to September 1999: 1.3774 instead of 1.5276).
ringApply() now keeps the start month in the data’s
metadata and wlai() uses it, so this route agrees with
wlai(ini.mnt = "Oct") on every block. The defect was
introduced in development version 0.9.2; the CRAN release 0.9.1 is not
affected.label_year in
wlai() and moveYr() from "start"
to "end", so that by default each hydrological year is
labeled by the year in which it ends (October 1998 to September 1999 is
labeled 1999), as in the CRAN release 0.9.1. "start"
remains available. hydro_year_id still holds the start
year.scacum()
with a vector of reference radii in sc.c scaled some cores
to another tree’s radius (with Prings05 and
Pradii03, 6 of the 8 cores). Every core is now scaled to
its own tree’s radius at rf.t. Fixed since development
version 0.9.2; added a regression test.tdForm() to the
behavior of the CRAN release 0.9.1: with on.time = TRUE
(the default) the relative time column time from
rtimes() is used when present, otherwise a year-like
column. In development version 0.9.4 the default had switched to
year whenever the data carried metadata, which
ringApply() adds automatically (checked with the 0.9.2,
0.9.3 and 0.9.4 builds). This affects the ringApply() help
route and modelFrame(Pchron), which again fit
log(x) ~ log(csx) + time. A time variable declared with
defineDataRoles(time = ...), on.time = FALSE,
or a formula string still decides as before.muleMan() help example
(modelFrame() on Prec and Temp
with moveYr() and wlai(), then
lmeForm) and muleMan() itself. The route
failed in development versions 0.9.2 to 0.9.4 (checked with their
builds), and in later development code the aridity-index model used
hydro_year_id, the start year, instead of the
hydrological-year label year. lmeForm() now
uses a time variable from the data’s metadata only when it was declared
with defineDataRoles(time = ...), so the model is
AI ~ year as in the CRAN release 0.9.1, and
muleMan() pairs ring year t with the hydrological year
ending in t. muleMan() also no longer fails when the
tree-ring data have a single time column or when both inputs have a
residual column of the same name.muleMan(): the plot and core labels of its output
could be swapped (for Pchron, core a of tree
17 in plot P16106 came out as
plot = a, sample = P16106), because the labels
were parsed from block names in an order that depended on the column
order of the tree-ring data. Each correlogram now takes its labels from
its own rows, whatever the column order. The CRAN release 0.9.1 labeled
them correctly; in the 0.9.2 to 0.9.4 builds the help-example route
failed before reaching muleMan().plot() now works on frametoLme() fits made
with res.data = FALSE: the residual fluctuations are
rebuilt from the model and show the same points as the plot of the same
fit with $fluc. The plot method added in development
version 0.9.4 stopped with “subscript out of bounds” on such fits, and
earlier versions, including the CRAN release 0.9.1, had no plot method
for them.amod(): the first increment of each series was
the whole transformed size, which is wrong when the cumulative size is
scaled (with scacum() and radii in sc.c). On
the ringApply() help route, the first basal-area increment
of core a of tree 17 in plot
P16106 (1897) was 5545 instead of 183. The first increment
is now the change from the size before the first ring (csx
minus the first ring width) to the first transformed size; later
increments and unscaled series are unchanged. The CRAN release 0.9.1
returned NA for first increments.wlai(): on long calendar data without
ini.mnt, every 12-month block started at the month of the
first row of cd, so the aridity indexes depended on the row
order (shuffling the rows of PTclim05 changed them by about
20% on average). Blocks now start at the first month of the earliest
year. Without a year column the first row’s month is still used, so rows
should then be in time order. Results on time-ordered data are
unchanged. The CRAN release 0.9.1 computed one index over all rows of
long data.levexp(): its help call
levexp(Pradii03, Prings05) returned an empty vector. The
integer year column was taken as a grouping column, and a
name with two levels such as P16106.17 could not match a
core label such as a.17.P16106. Time columns are no longer
taken as grouping columns, and a name now matches a split label when its
dot-separated parts are a contiguous run of the label’s parts, read in
either direction; each core now gets its own tree’s radius. Single-part
names match as before. The CRAN release 0.9.1 returned only the two
cores of tree 7 in plot P44005.ringApply(): named arguments that vary by block,
such as sc.c = Pradii03, were handed to the blocks by
position, so their names were ignored and the result depended on the
order of the vector’s elements (with rev(Pradii03) every
core of the help route was scaled to another tree’s radius). A named
vector whose names match the split labels is now given to each block by
name through levexp(); other arguments are recycled over
blocks as before. If the names match some blocks but not all, a warning
names the argument and the unmatched blocks, and the values are given by
position. The CRAN release 0.9.1 was also affected: it handed
sc.c out by position, and with rev(Pradii03) 6
of the 8 cores got another tree’s radius.cClass()), and
character columns are now also treated as groups (0.9.1 ignored them);
whole-number numeric columns are time candidates, and other numeric
columns are responses. The month column (named month, or a
factor whose levels are month names) is never a group. The development
versions 0.9.2-0.9.4 guessed roles from column names (lists such as
plot, tree, zone, site, year, hydro_year_id); those lists are removed.
Roles declared with defineDataRoles() override the type
rule; metadata that ringApply() creates automatically no
longer does. On the bundled data the documented results are unchanged,
except that month in PTclim05 is no longer a
grouping column (lmeForm(PTclim05) is
pr ~ year | plot, and slitFrame(PTclim05)
splits by plot only). Year can still be a random grouping level: declare
it with defineDataRoles(groups = ...) or add a factor copy
of it.rtimes(), scacum(), moveYr()
and wlai() find their time columns by the package’s column
names: year (or hydro_year_id from
moveYr()), month and time; a
month column may also be a factor whose levels are month names. The
development versions 0.9.2-0.9.4 also read aliases (yr,
calendar_year, hydro_year,
water_year, mon, mnt,
mo) and other time units (week, day, hour, minute,
rel_time, ring_time, cambial_age, age); these are no longer read.
moveYr() stops if there is no column named
year; scacum() stops if rf.t is
given and there is no year, hydro_year_id or
time column (it used to fall back silently to each block’s
last value); rtimes() and wlai() warn when
none of year, hydro_year_id,
month or time is present. The CRAN release
0.9.1 never had the aliases.scacum() reads its values from the column
x, as in the CRAN release 0.9.1; a response declared with
defineDataRoles() takes precedence, and without either
scacum() stops. wlai() reads precipitation
from pr and temperature from tm, the package’s
column names; declared inputs take precedence (declared pr
and tm by name, otherwise the declared order, precipitation
first). Without pr or tm, wlai()
uses the first two numeric columns and warns which ones; this fallback
follows 0.9.1, which read columns 1 and 2 by position. The name lists
added in development versions 0.9.2-0.9.4 (trw,
rw, rwi, abi; pm,
prec, ppt, precip,
rain, temp, tmean,
tavg and others) are removed.frametoLme() and modelFrame()
now say that rows with missing values in the fitted variables or
grouping columns are dropped without a message (e.g. the rows where
rtimes() gives no time), and describe the default random
part and how to pass random =; rtimes() says
which rows get NA time; moveYr() has a Value section
explaining that the calendar year is relabeled and how to recover
it.frametoLme(): when a column was both a grouping
level and a time column (for example year declared in
groups with defineDataRoles()),
$fluc carried it twice, the second copy as
year.1. It now carries it once.defineDataRoles() example uses the bundled data’s
own columns (it named zone and health, which
no bundled dataset has, and stopped with an error).frametoLme(),
summary(), print() and the printed summary of
frametoLme objects.frametoLme() and
modelFrame() fits: the “Groups” line also listed nlme’s
counts for the model matrix and response (X 1,
y 1); it now lists only the grouping levels.frametoLme() and
modelFrame() fits: the fixed-effects table was printed in
scientific notation, including the DF column (9.8200e+02);
it is now formatted column by column as in nlme’s summary, with whole DF
and p-values rounded to 4 decimals.modelFrame()
(fitted model, Friedman smoother and processed data only) and for
summary(), print() and the printed summary of
modelFrame objects.frametoLme(): refitting a fit’s model data
(fit$model$data) with tdForm or
lmeForm reversed the nesting
(sample/tree/plot), because the fitting copy listed the
grouping columns in reverse. The copy now keeps the input’s column
order.frametoLme(): the model data stored in the fit
(fit$model$data) kept only the time variable of the fitted
model, so refitting a year model with tdForm(log.t = TRUE),
as in the BIOdry 0.8 example, silently used log(year)
instead of log(time). The model data now keep all time
columns; rows are still dropped only for missing fitted variables and
grouping columns, and $fluc is unchanged.frametoLme() examples compare the two Zeide time
forms (linear and logarithmic time, log.t) by maximum
likelihood under a random part the bundled data support (a tree
intercept and a tree-level log(csx) slope), refit the
preferred form with REML, and show the default random part’s near-zero
variance components for comparison; the frametoLme(),
tdForm() and modelFrame() help pages explain
the time forms, singular fits and how to pass a simpler random
part.moveYr() example on the bundled
PTclim05: hydrological-year labels, recovering the calendar
year, label_year and ini.mnt.frametoLme() and
modelFrame() fits: nlme’s default
aspect = "xy" collapsed the panels to thin strips, and the
axes carried internal column names (.mf_resid__,
.mf_fitted__, .model_resid__). The panels now
fill the plotting area and the axes read “Pearson residuals” and “Fitted
values” (or the time variable). The plot of processed data
(modelFrame(form = NULL)) also fills its panels.
aspect, xlab and ylab given by
the user are kept.plot() of
frametoLme and modelFrame objects (residuals
over time; residuals against fitted values, by core and by plot;
processed series with form = NULL).plot() of
frametoFriedman objects and of modelFrame()
Friedman fits): the panels now fill the plotting area, and the axes read
“Ratio index” (or “Difference index” with
difference = TRUE) and “Fitted smooth” or the time variable
instead of the column names x.idx and x.fit;
aspect, xlab and ylab given by
the user are kept.frametoFriedman() and modelFrame()
Friedman fits: the printed status table no longer carries the note
column, which wrapped into a mostly empty block; notes are listed below
the table, one short line per series with its number of NA values (the
full note and the count n_na are kept in the series table).
frametoFriedman() lists the series in the order of their
first rows in the data, as the modelFrame() path does,
instead of factor-level order.plot() of frametoFriedman objects
with levels coarser than the series
(e.g. levels = 'plot'): one line was drawn through all
points of a panel, joining different cores; each series now has its own
line within the panel, with a key. The default plot is unchanged.FriedmanForm(),
frametoFriedman() and the summary(),
print() and plot() methods of
frametoFriedman objects (ratio and difference indices,
series status, panels by plot).muleMan() and its
plot() method (biomass and aridity-index fluctuations,
Mantel correlograms per core).anova() example for modelFrame
objects: sequential F tests of one biomass model, and AIC/BIC of the
time forms t and ln t fitted by ML.plot() of muleMan objects orders the
panels by plot, tree (as numbers) and core, and labels the axes “Lag”
and “Mantel r” unless xlab or ylab are given
(they were ecodist’s lag and mantelr).anova() of frametoLme
objects: description, arguments and a runnable example (F tests of one
fit; ML comparison of the time forms t and ln t).update() of frametoLme objects: the
refitted object’s call shows the original data expression instead of the
internal placeholder ..rd... Fits are unchanged.normalizeGroupLevels() on fitted objects
(frametoLme, modelFrame) without
groups orders the grouping levels of $fluc:
the grouping variables come from the metadata of $fluc,
else from the model’s grouping formula. Before, the call left
$fluc unchanged (tree levels 18, 7, 56, 17 in the
frametoLme example fit; now 7, 17, 18, 56).normalizeGroupLevels() orders a grouping column as
numbers only when all its non-missing labels read as numbers, and keeps
the labels themselves as levels (e.g. “07” stays “07” and comes before
17). Before, a label that did not read as a number (“T7” next to 17, 18,
56), or that changed when read as one (“07”, “1.0”), became NA.update() of frametoLme
objects: description, arguments and a runnable example (ML refit; the
time forms t and ln t).normalizeGroupLevels(): description,
arguments and a runnable example (fitted object and data frame).plot() of wlai objects:
description, details, arguments and an example on the bundled
PTclim05 (it simulated random climate data).wlai() example uses the bundled
PTclim05 (one calendar year; one index per plot and
hydrological year; a diagram) instead of random data.moveYr() help page: descriptions of the arguments
cd, ini.mnt, keep_hydro_id,
hydro_id_name and validate.plot() of wlai objects: the block label
printed after the aridity index follows the year column of
the block, so it follows label_year: with the default
'end', October 2000 to September 2001 of plot P44005 is
labeled P44005.2001 (it showed the start year, P44005.2000). Block
names, used by which, still hold
hydro_year_id.frametoLme,
modelFrame and frametoFriedman objects, is
declared in Imports.\code markup
(plot() and summary() of
frametoLme objects), double-escaped markup in
scacum(), the links to the ‘nlme’ plot methods for grouped
data (plot.nfnGroupedData,
plot.nmGroupedData), and the cClass()
title.|>.AIC, BIC,
as.formula, ave, fitted,
logLik, resid and setNames from
‘stats’.wlai() help page: the Value section describes the
returned data frame (it described a numeric index and a plot).frametoLme() drops only rows with missing values in the
fitted variables or the grouping columns. The CRAN release 0.9.1 dropped
rows with a missing value in any column, so fits can now use more rows
(20 more in the modelFrame() biomass example).mUnits() help page: “milli” spelled correctly.Strengthened the internal helper chain used by
modelFrame() and related workflows for multilevel tree-ring
and climate data.
Improved class and hierarchy detection in
cClass().
Date, and
POSIXt columns.Improved formula construction in lmeForm() and
tdForm().
lmeForm() now resolves response, time covariates, and
grouping levels more defensively on multilevel long data.tdForm() now preserves the intended formulation
log(x) ~ log(csx) + f(time).tdForm() now checks tree-growth inputs more explicitly
and warns or stops more clearly when the input looks climatic or does
not contain the expected growth variables.Improved argument and level expansion helpers.
arguSelect() now validates target functions more
safely, handles MoreArgs more defensively, and warns when
direct arguments or MoreArgs entries are dropped.levexp() now avoids the previous
slitFrame() + grep() bottleneck, uses
token-based matching, and behaves more predictably on multilevel
labels.slitFrame() now detects grouping columns more robustly
and keeps split metadata for downstream helpers.Improved hydrological-year handling in moveYr().
label_year = c("start", "end").hydro_year_id so
downstream functions can group annual climatic blocks independently of
the displayed year label.Improved Walter–Lieth aridity workflows.
wlai() now works more safely on long multilevel climate
data by splitting into annual blocks instead of treating long
concatenated tables as one continuous series.wlai() now preserves hydrological month order inside
each block.plot.wlai() now supports multi-block wlai
objects more safely, allows block selection without leaving the standard
S3 plot() interface, and defaults to plotting the first
available block when no selector is provided.plot.wlai() now uses a black 100 mm line, a blue
compressed precipitation band above 100 mm, and automatic top headroom
for legends and labels.plot.wlai() to document
multilevel block selection, plotting defaults, and Walter–Lieth
styling.Improved split/apply helpers for multilevel tree-ring and climate data.
ringApply() now respects the resolved lv
more consistently, orders rows within each split block on the remaining
time variables before applying fn, and returns columns in
the order: records, time variables, then factor hierarchy.rtimes() now works both as a block-level helper and on
multilevel data frames, including grouped time reconstruction through
lv.scacum() now works both as a block-level helper and on
multilevel data frames, including block-wise ordering before cumulative
growth reconstruction.amod() now works on block-level series and multilevel
data frames, applies the allometric model to cumulative growth
internally, returns both allometric x and csx,
and avoids introducing an initial NA in the reconstructed
increments.Improved reshaping in shiftFrame().
split_pattern while keeping dot splitting as the
default.tm and pm instead of dropping one variable
during reshaping.Improved model fitting wrappers.
frametoLme() now orders multilevel long data before
fitting, rebuilds residual series from real time and grouping columns
more safely, and wraps residual outputs more consistently.modelFrame() now distinguishes long data frames from
non-data-frame lists more safely, handles staged
fn/lv recursion more defensively, applies
mUnits() to record-like numeric columns more
conservatively, and passes validation settings through the helper
chain.modelFrame() handling of long multilevel
inputs by resolving stage levels against the current hierarchy without
silently dropping valid grouping columns.Added or expanded inlinedocs details in patched helpers so the internal contracts are documented more explicitly.
ringApply(),
shiftFrame(), amod(), and
plot.wlai().anova.modelFrame.Rd: linked anova.lme to
the nlme package.frametoLme.Rd: linked lme,
nlme, and groupedData to
nlme.lmeForm.Rd: linked groupedData to
nlme.modelFrame.Rd: linked lme,
nlme, and groupedData to
nlme.muleMan.Rd: linked groupedData to
nlme, mgram to ecodist,
and ecodist correctly.shiftFrame.Rd: linked groupedData to
nlme.summary.modelFrame.Rd: linked summary.lme
to nlme.Pchron.Rd,
Prec.Rd, and Temp.Rd.shiftFrame: The internal
implementation of data.frame() now uses
stringsAsFactors = TRUE.Developed five new S3 methods:
anova.modelFrameplot.modelFrameplot.muleManplot.wlaisummary.modelFrameChanges in modelFrame:
Changes in muleMan:
New binary datasets added to data/
folder:
Pchron.RData, Prec.RData, and
Temp.RData (contain dendroclimatic chronologies).New function mUnits: Converts
metric units in dendroclimatic chronologies.
Changes in amod:
New function cClclass:
colclass function.tdForm:
ringLme:
frametoLme() to improve
lme implementation from the nlme
package.shiftFrame:
Updated algorithm to shift ring-data frames into multilevel data
frames, fixing an internal error in R < 3.2.0.
Added new default argument:
lev.nm = c("plot", "tree", "sample")This argument provides names for the factor-level columns in reshaped multilevel data frames.
muleMan:
groupedData object.plot.man = TRUEpsig = 0.05groupedData object using other
trellis-graph functions. (See function examples.)