Skip to content

Commit d12cd3e

Browse files
author
maechler
committed
fix dealing with erronous seasonal = <numeric>; sync arima0() code & doc
git-svn-id: https://svn.r-project.org/R/trunk@87520 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 48ab7b4 commit d12cd3e

File tree

6 files changed

+74
-54
lines changed

6 files changed

+74
-54
lines changed

doc/NEWS.Rd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,11 @@
515515
516516
\item \code{dev.capabilities() $ events} now reports \code{"Idle"} if
517517
the device provides it, fixing \PR{18836}, thanks to \I{Trevor Davis}.
518-
}
518+
519+
\item \code{arima(.., seasonal = <wrong-vector>)} correctly errors
520+
now, ditto for \code{arima0()}, thanks to \I{Norbert Kuder}'s report
521+
on the R-devel list.
522+
}
519523
}
520524
}
521525

src/library/stats/R/arima.R

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# File src/library/stats/R/arima.R
22
# Part of the R package, https://www.R-project.org
33
#
4-
# Copyright (C) 2002-2015 The R Core Team
4+
# Copyright (C) 2002-2025 The R Core Team
55
#
66
# This program is free software; you can redistribute it and/or modify
77
# it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ arima <- function(x, order = c(0L, 0L, 0L),
5252
.Call(C_ARIMA_Like, y, mod, 0L, TRUE)
5353
}
5454

55-
## the objective function called by optim()
55+
## the objective function called by optim(); using {coef, mask, arma, mod, ....}
5656
armafn <- function(p, trans)
5757
{
5858
par <- coef
@@ -124,10 +124,11 @@ arima <- function(x, order = c(0L, 0L, 0L),
124124
if(!is.numeric(seasonal$order) || length(seasonal$order) != 3L
125125
|| any(seasonal$order < 0L))
126126
stop("'seasonal$order' must be a non-negative numeric vector of length 3")
127-
} else if(is.numeric(order)) {
128-
if(length(order) == 3L) seasonal <- list(order=seasonal)
129-
else ("'seasonal' is of the wrong length")
130-
} else stop("'seasonal' must be a list with component 'order'")
127+
} else if(is.numeric(seasonal)) { # meant to be seasonal$order
128+
if(length(seasonal) != 3L || any(seasonal < 0))
129+
stop("if not a list, 'seasonal' must be a non-negative numeric vector of length 3")
130+
seasonal <- list(order=seasonal)
131+
} else stop("'seasonal' is neither a list with component 'order' nor a numeric vector of length 3")
131132

132133
if (is.null(seasonal$period) || is.na(seasonal$period) || seasonal$period == 0)
133134
seasonal$period <- frequency(x)
@@ -290,14 +291,15 @@ arima <- function(x, order = c(0L, 0L, 0L),
290291
}
291292
}
292293
trarma <- .Call(C_ARIMA_transPars, init, arma, transform.pars)
293-
mod <- makeARIMA(trarma[[1L]], trarma[[2L]], Delta, kappa, SSinit)
294294
res <- if(no.optim)
295295
list(convergence = 0, par = numeric(),
296296
value = armafn(numeric(), as.logical(transform.pars)))
297-
else
297+
else {
298+
mod <- makeARIMA(trarma[[1L]], trarma[[2L]], Delta, kappa, SSinit)
298299
optim(init[mask], armafn, method = optim.method,
299300
hessian = TRUE, control = optim.control,
300301
trans = as.logical(transform.pars))
302+
}
301303
if(res$convergence > 0)
302304
warning(gettextf("possible convergence problem: optim gave code = %d",
303305
res$convergence), domain = NA)
@@ -333,9 +335,8 @@ arima <- function(x, order = c(0L, 0L, 0L),
333335
} else var <- if(no.optim) numeric() else solve(res$hessian * n.used)
334336
trarma <- .Call(C_ARIMA_transPars, coef, arma, FALSE)
335337
mod <- makeARIMA(trarma[[1L]], trarma[[2L]], Delta, kappa, SSinit)
336-
val <- if(ncxreg > 0L)
337-
arimaSS(x - xreg %*% coef[narma + (1L:ncxreg)], mod)
338-
else arimaSS(x, mod)
338+
val <- arimaSS(if(ncxreg > 0L) x - xreg %*% coef[narma + (1L:ncxreg)]
339+
else x, mod)
339340
sigma2 <- val[[1L]][1L]/n.used
340341
}
341342
value <- 2 * n.used * res$value + n.used + n.used * log(2 * pi)

src/library/stats/R/arma0.R

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# File src/library/stats/R/arma0.R
22
# Part of the R package, https://www.R-project.org
33
#
4-
# Copyright (C) 1999-2019 The R Core Team
4+
# Copyright (C) 1999-2025 The R Core Team
55
#
66
# This program is free software; you can redistribute it and/or modify
77
# it under the terms of the GNU General Public License as published by
@@ -16,8 +16,8 @@
1616
# A copy of the GNU General Public License is available at
1717
# https://www.R-project.org/Licenses/
1818

19-
arima0 <- function(x, order = c(0, 0, 0),
20-
seasonal = list(order = c(0, 0, 0), period = NA),
19+
arima0 <- function(x, order = c(0L, 0L, 0L),
20+
seasonal = list(order = c(0L, 0L, 0L), period = NA),
2121
xreg = NULL, include.mean = TRUE, delta = 0.01,
2222
transform.pars = TRUE, fixed = NULL, init = NULL,
2323
method = c("ML", "CSS"), n.cond,
@@ -41,7 +41,7 @@ arima0 <- function(x, order = c(0, 0, 0),
4141
{
4242
## polyroot can't cope with leading zero.
4343
q <- length(ma)
44-
q0 <- max(which(c(1,ma) != 0)) - 1
44+
q0 <- max(which(c(1,ma) != 0)) - 1L
4545
if(!q0) return(ma)
4646
roots <- polyroot(c(1, ma[1L:q0]))
4747
ind <- Mod(roots) < 1
@@ -55,9 +55,10 @@ arima0 <- function(x, order = c(0, 0, 0),
5555
}
5656

5757
series <- deparse1(substitute(x))
58-
if(NCOL(x) > 1)
58+
if(NCOL(x) > 1L)
5959
stop("only implemented for univariate time series")
6060
method <- match.arg(method)
61+
6162
x <- as.ts(x)
6263
if(!is.numeric(x))
6364
stop("'x' must be numeric")
@@ -72,12 +73,13 @@ arima0 <- function(x, order = c(0, 0, 0),
7273
if(is.null(seasonal$order))
7374
stop("'seasonal' must be a list with component 'order'")
7475
if(!is.numeric(seasonal$order) || length(seasonal$order) != 3L
75-
|| any(seasonal$order < 0))
76+
|| any(seasonal$order < 0L))
7677
stop("'seasonal$order' must be a non-negative numeric vector of length 3")
77-
} else if(is.numeric(order)) {
78-
if(length(order) == 3) seasonal <- list(order=seasonal)
79-
else ("'seasonal' is of the wrong length")
80-
} else stop("'seasonal' must be a list with component 'order'")
78+
} else if(is.numeric(seasonal)) { # meant to be seasonal$order
79+
if(length(seasonal) != 3L || any(seasonal < 0))
80+
stop("if not a list, 'seasonal' must be a non-negative numeric vector of length 3")
81+
seasonal <- list(order=seasonal)
82+
} else stop("'seasonal' is neither a list with component 'order' nor a numeric vector of length 3")
8183

8284
if(is.null(seasonal$period) || is.na(seasonal$period)
8385
|| seasonal$period == 0) seasonal$period <- frequency(x)
@@ -167,15 +169,15 @@ arima0 <- function(x, order = c(0, 0, 0),
167169
if(!arCheck(init[1L:arma[1L]]))
168170
stop("non-stationary AR part")
169171
if(arma[3L] > 0)
170-
if(!arCheck(init[sum(arma[1L:2]) + 1L:arma[3L]]))
172+
if(!arCheck(init[sum(arma[1L:2L]) + 1L:arma[3L]]))
171173
stop("non-stationary seasonal AR part")
172174
## enforce invertibility
173175
if(arma[2L] > 0) {
174176
ind <- arma[1L] + 1L:arma[2L]
175177
init[ind] <- maInvert(init[ind])
176178
}
177179
if(arma[4L] > 0) {
178-
ind <- sum(arma[1L:3]) + 1L:arma[4L]
180+
ind <- sum(arma[1L:3L]) + 1L:arma[4L]
179181
init[ind] <- maInvert(init[ind])
180182
}
181183
init <- .Call(C_Invtrans, G, as.double(init))
@@ -210,12 +212,12 @@ arima0 <- function(x, order = c(0, 0, 0),
210212
class(resid) <- "ts"
211213
n.used <- sum(!is.na(resid))
212214
nm <- NULL
213-
if(arma[1L] > 0) nm <- c(nm, paste0("ar", 1L:arma[1L]))
214-
if(arma[2L] > 0) nm <- c(nm, paste0("ma", 1L:arma[2L]))
215-
if(arma[3L] > 0) nm <- c(nm, paste0("sar", 1L:arma[3L]))
216-
if(arma[4L] > 0) nm <- c(nm, paste0("sma", 1L:arma[4L]))
215+
if(arma[1L] > 0L) nm <- c(nm, paste0("ar", 1L:arma[1L]))
216+
if(arma[2L] > 0L) nm <- c(nm, paste0("ma", 1L:arma[2L]))
217+
if(arma[3L] > 0L) nm <- c(nm, paste0("sar", 1L:arma[3L]))
218+
if(arma[4L] > 0L) nm <- c(nm, paste0("sma", 1L:arma[4L]))
217219
fixed[mask] <- coef
218-
if(ncxreg > 0) {
220+
if(ncxreg > 0L) {
219221
nm <- c(nm, cn)
220222
if(!orig.xreg) {
221223
ind <- narma + 1L:ncxreg
@@ -255,11 +257,9 @@ print.arima0 <- function(x, digits = max(3L, getOption("digits") - 3L),
255257
print.default(coef, print.gap = 2)
256258
cm <- x$call$method
257259
if(is.null(cm) || cm != "CSS")
258-
cat("\nsigma^2 estimated as ",
259-
format(x$sigma2, digits = digits),
260-
": log likelihood = ", format(round(x$loglik,2)),
261-
", aic = ", format(round(x$aic,2)),
262-
"\n", sep = "")
260+
cat("\nsigma^2 estimated as ", format(x$sigma2, digits = digits),
261+
": log likelihood = ", format(round(x$loglik, 2L)),
262+
", aic = ", format(round(x$aic, 2L)), "\n", sep = "")
263263
else
264264
cat("\nsigma^2 estimated as ",
265265
format(x$sigma2, digits = digits),
@@ -294,12 +294,12 @@ predict.arima0 <-
294294
xm <- drop(as.matrix(newxreg) %*% coefs[-(1L:narma)])
295295
} else xm <- 0
296296
## check invertibility of MA part(s)
297-
if(arma[2L] > 0) {
297+
if(arma[2L] > 0L) {
298298
ma <- coefs[arma[1L] + 1L:arma[2L]]
299299
if(any(Mod(polyroot(c(1, ma))) < 1))
300300
warning("MA part of model is not invertible")
301301
}
302-
if(arma[4L] > 0) {
302+
if(arma[4L] > 0L) {
303303
ma <- coefs[sum(arma[1L:3L]) + 1L:arma[4L]]
304304
if(any(Mod(polyroot(c(1, ma))) < 1))
305305
warning("seasonal MA part of model is not invertible")

src/library/stats/man/arima.Rd

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
% File src/library/stats/man/arima.Rd
22
% Part of the R package, https://www.R-project.org
3-
% Copyright 1995-2024 R Core Team
3+
% Copyright 1995-2025 R Core Team
44
% Distributed under GPL 2 or later
55

66
\name{arima}
@@ -24,21 +24,22 @@ arima(x, order = c(0L, 0L, 0L),
2424
\arguments{
2525
\item{x}{a univariate time series}
2626

27-
\item{order}{A specification of the non-seasonal part of the ARIMA
27+
\item{order}{a specification of the non-seasonal part of the ARIMA
2828
model: the three integer components \eqn{(p, d, q)} are the AR order, the
2929
degree of differencing, and the MA order.}
3030

31-
\item{seasonal}{A specification of the seasonal part of the ARIMA
31+
\item{seasonal}{a specification of the seasonal part of the ARIMA
3232
model, plus the period (which defaults to \code{frequency(x)}).
33-
This may be a list with components \code{order} and
33+
This may be a \code{\link{list}} with components \code{order} and
3434
\code{period}, or just a numeric vector of length 3 which
3535
specifies the seasonal \code{order}. In the latter case the
3636
default period is used.}
3737

3838
\item{xreg}{Optionally, a vector or matrix of external regressors,
3939
which must have the same number of rows as \code{x}.}
4040

41-
\item{include.mean}{Should the ARMA model include a mean/intercept term? The
41+
\item{include.mean}{logical indicating if the ARMA model should include a
42+
mean/intercept term. The
4243
default is \code{TRUE} for undifferenced series, and it is ignored
4344
for ARIMA models with differencing.}
4445

src/library/stats/man/arima0.Rd

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
% File src/library/stats/man/arima0.Rd
22
% Part of the R package, https://www.R-project.org
3-
% Copyright 1995-2024 R Core Team
3+
% Copyright 1995-2025 R Core Team
44
% Distributed under GPL 2 or later
55

66
\name{arima0}
@@ -12,6 +12,7 @@
1212
\description{
1313
Fit an ARIMA model to a univariate time series, and forecast from
1414
the fitted model.
15+
For new projects, consider using \code{\link{arima}()} instead.
1516
}
1617
\usage{
1718
arima0(x, order = c(0, 0, 0),
@@ -25,16 +26,16 @@ arima0(x, order = c(0, 0, 0),
2526
\arguments{
2627
\item{x}{a univariate time series}
2728

28-
\item{order}{A specification of the non-seasonal part of the ARIMA
29-
model: the three components \eqn{(p, d, q)} are the AR order, the
29+
\item{order}{a specification of the non-seasonal part of the ARIMA
30+
model: the three integer components \eqn{(p, d, q)} are the AR order, the
3031
degree of differencing, and the MA order.}
3132

32-
\item{seasonal}{A specification of the seasonal part of the ARIMA
33+
\item{seasonal}{a specification of the seasonal part of the ARIMA
3334
model, plus the period (which defaults to \code{frequency(x)}).
34-
This should be a list with components \code{order} and
35-
\code{period}, but a specification of just a numeric vector of
36-
length 3 will be turned into a suitable list with the specification
37-
as the \code{order}.}
35+
This may be a \code{\link{list}} with components \code{order} and
36+
\code{period}, or just a numeric vector of length 3 which
37+
specifies the seasonal \code{order}. In the latter case the
38+
default period is used.}
3839

3940
\item{xreg}{Optionally, a vector or matrix of external regressors,
4041
which must have the same number of rows as \code{x}.}
@@ -47,7 +48,7 @@ arima0(x, order = c(0, 0, 0),
4748
\item{delta}{A value to indicate at which point \sQuote{fast
4849
recursions} should be used. See the \sQuote{Details} section.}
4950

50-
\item{transform.pars}{Logical. If true, the AR parameters are
51+
\item{transform.pars}{logical; if true, the AR parameters are
5152
transformed to ensure that they remain in the region of
5253
stationarity. Not used for \code{method = "CSS"}.}
5354

@@ -62,10 +63,10 @@ arima0(x, order = c(0, 0, 0),
6263
regression coefficients. Values already specified in \code{fixed}
6364
will be ignored.}
6465

65-
\item{method}{Fitting method: maximum likelihood or minimize
66+
\item{method}{fitting method: maximum likelihood or minimize
6667
conditional sum-of-squares. Can be abbreviated.}
6768

68-
\item{n.cond}{Only used if fitting by conditional-sum-of-squares: the
69+
\item{n.cond}{only used if fitting by conditional-sum-of-squares: the
6970
number of initial observations to ignore. It will be ignored if
7071
less than the maximum lag of an AR term.}
7172

@@ -204,7 +205,7 @@ arima0(x, order = c(0, 0, 0),
204205

205206
Harvey, A. C. and McKenzie, C. R. (1982).
206207
Algorithm AS 182: An algorithm for finite sample prediction from ARIMA
207-
processes.
208+
processes.
208209
\emph{Applied Statistics}, \bold{31}, 180--187.
209210
\doi{10.2307/2347987}.
210211

@@ -216,7 +217,9 @@ arima0(x, order = c(0, 0, 0),
216217
}
217218

218219
\note{
219-
This is a preliminary version, and will be replaced by \code{\link{arima}}.
220+
This has been a preliminary version, and is mostly replaced by
221+
\code{\link{arima}}, notably in the presence of missing values.
222+
\code{arima0()} remains mostly for reproducibility reasons.
220223

221224
The standard errors of prediction exclude the uncertainty in the
222225
estimation of the ARMA model and the regression coefficients.

tests/reg-tests-1e.R

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,17 @@ if(length(iLA) && nzchar(La_version())) { cat("sessionInfo - La_* checking: ")
17121712
## the "LAPACK: .." was entirely empty when si$LAPACK was ""
17131713

17141714

1715+
## arima(*, seasonal = <numeric>)
1716+
(m <- tryCmsg( arima(presidents, order=c(2,0,1), seasonal=c(1, 0)) ))
1717+
stopifnot(exprs = {
1718+
grepl("'seasonal'", m, fixed=TRUE)
1719+
!englishMsgs ||
1720+
grepl("must be a non-negative numeric vector", m, fixed=TRUE)
1721+
})
1722+
## gave solve.default() error (as wrong model failed fitting)
1723+
1724+
1725+
17151726
## keep at end
17161727
rbind(last = proc.time() - .pt,
17171728
total = proc.time())

0 commit comments

Comments
 (0)