Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Honour numeric 'breaks' option in confidence intervals in bfast() #103

Merged
merged 8 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: bfast
Version: 1.7.0
Version: 1.6.1.9999
Title: Breaks for Additive Season and Trend
Authors@R: c(person(given = "Jan", family = "Verbesselt", role = c("aut"), email = "Jan.Verbesselt@wur.nl"),
person(given = "Dainius", family = "Masiliunas", role = c("aut", "cre"),
Expand Down
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Changes in Version 1.7.0
anything equal to or below 0 in 'level' will skip the sctest.

o Fixed a bug where bfastpp() would throw an error when annual data is input.

o Rework of the 'breaks' argument in bfast(), it now works correctly with a
numeric input and gives the opportunity to specify the breaks/statistic for
computing the optimal number of breaks separately per component.

Changes in Version 1.6.1

Expand Down
28 changes: 20 additions & 8 deletions R/bfast.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,12 @@
#' time series is 1) "none" can be selected to avoid fitting a seasonal model.
#' @param max.iter maximum amount of iterations allowed for estimation of
#' breakpoints in seasonal and trend component.
#' @param breaks integer specifying the maximal number of breaks to be
#' calculated. By default the maximal number allowed by h is used.
#' @param breaks either an integer specifying the number of breaks to compute,
#' or a string specifying a statistic with which to compute
#' the optimal number of breakpoints (see [strucchangeRcpp::breakpoints()] for
#' more information). If one value is given, it is used for both the trend and
#' seasonal components, and if two are given, the first one is considered to be
#' for the trend and the second for the seasonal component.
#' @param hpc A character specifying the high performance computing support.
#' Default is "none", can be set to "foreach". Install the "foreach" package
#' for hpc support.
Expand Down Expand Up @@ -93,6 +97,14 @@ bfast <- function (Yt, h = 0.15, season = c("dummy", "harmonic", "none"),
}
## Get Arguments
season <- match.arg(season)
if (length(breaks) > 1)
{
breaks.Vt <- breaks[[1]]
breaks.Wt <- breaks[[2]]
} else {
breaks.Vt <- breaks
breaks.Wt <- breaks
}
level <- rep(level, length.out = 2)
ti <- time(Yt)
f <- frequency(Yt) # on cycle every f time points (seasonal cycle)
Expand Down Expand Up @@ -151,8 +163,8 @@ bfast <- function (Yt, h = 0.15, season = c("dummy", "harmonic", "none"),
Vt <- Yt - St # Deasonalized Time series
p.Vt <- sctest(efp(Vt ~ ti, h = h, type = type))
if (p.Vt$p.value <= level[1]) {
bp.Vt <- breakpoints(Vt ~ ti, h = h, breaks = breaks, na.action=na.exclude,hpc = hpc)
nobp.Vt <- is.na(breakpoints(bp.Vt)[1])
bp.Vt <- breakpoints(Vt ~ ti, h = h, breaks = breaks.Vt, na.action=na.exclude,hpc = hpc)
nobp.Vt <- is.na(breakpoints(bp.Vt, breaks = breaks.Vt)[1])
} else {
nobp.Vt <- TRUE
bp.Vt <- NA
Expand All @@ -167,7 +179,7 @@ bfast <- function (Yt, h = 0.15, season = c("dummy", "harmonic", "none"),
ci.Vt <- NA
} else {
fm1 <- lm(Vt[which(!is.na(Yt))] ~ breakfactor(bp.Vt)/ti[which(!is.na(Yt))] )
ci.Vt <- confint(bp.Vt, het.err = FALSE)
ci.Vt <- confint(bp.Vt, het.err = FALSE, breaks = breaks.Vt)
Vt.bp <- ci.Vt$confint[, 2]
# Define empty copy of original time series
Tt <- ts(data=NA,start = ti[1], end = ti[length(ti)],frequency = f)
Expand All @@ -185,9 +197,9 @@ bfast <- function (Yt, h = 0.15, season = c("dummy", "harmonic", "none"),
Wt <- Yt - Tt
p.Wt <- sctest(efp(smod, h = h, type = type)) # preliminary test
if (p.Wt$p.value <= level[2]) {
bp.Wt <- breakpoints(smod, h = h, breaks = breaks,
bp.Wt <- breakpoints(smod, h = h, breaks = breaks.Wt,
hpc = hpc)
nobp.Wt <- is.na(breakpoints(bp.Wt)[1])
nobp.Wt <- is.na(breakpoints(bp.Wt, breaks = breaks.Wt)[1])
}
else {
nobp.Wt <- TRUE
Expand All @@ -208,7 +220,7 @@ bfast <- function (Yt, h = 0.15, season = c("dummy", "harmonic", "none"),
sm1 <- lm(Wt[!is.na(Wt)] ~ (
co[!is.na(Wt)] + si[!is.na(Wt)] + co2[!is.na(Wt)] + si2[!is.na(Wt)] + co3[!is.na(Wt)] + si3[!is.na(Wt)]
) %in% breakfactor(bp.Wt))
ci.Wt <- confint(bp.Wt, het.err = FALSE)
ci.Wt <- confint(bp.Wt, het.err = FALSE, breaks = breaks.Wt)
Wt.bp <- ci.Wt$confint[, 2]

# Define empty copy of original time series
Expand Down