CausalImpact {CausalImpact}R Documentation

Inferring causal impact using structural time-series models


CausalImpact() performs causal inference through counterfactual predictions using a Bayesian structural time-series model.

See the package documentation ( to understand the underlying assumptions. In particular, the model assumes that the time series of the treated unit can be explained in terms of a set of covariates which were themselves not affected by the intervention whose causal effect we are interested in.

The easiest way of running a causal analysis is to call CausalImpact() with data, pre.period, post.period, model.args (optional), and alpha (optional). In this case, a time-series model is automatically constructed and estimated. The argument model.args offers some control over the model. See Example 1 below.

An alternative is to supply a custom model. In this case, the function is called with bsts.model, post.period.response, and alpha (optional). See Example 3 below.


  CausalImpact(data = NULL, pre.period = NULL,
    post.period = NULL, model.args = NULL,
    bsts.model = NULL, post.period.response = NULL,
    alpha = 0.05)



Time series of response variable and any covariates. This can be a zoo object, a vector, a matrix, or a data.frame. In any of these cases, the response variable must be in the first column, and any covariates in subsequent columns. A zoo object is recommended, as its time indices will be used to format the x-axis in plot().


A vector specifying the first and the last time point of the pre-intervention period in the response vector y. This period can be thought of as a training period, used to determine the relationship between the response variable and the covariates. If data is a zoo object with a time attribute, pre.period must be indicated using the same time scale (i.e. using the same class as time(data), see Example 2 below). If data doesn't have a time attribute, post.period is indicated with indices.


A vector specifying the first and the last day of the post-intervention period we wish to study. This is the period after the intervention has begun whose effect we are interested in. The relationship between response variable and covariates, as determined during the pre-period, will be used to predict how the response variable should have evolved during the post-period had no intervention taken place. If data is a zoo object with a time attribute, post.period must be indicated using the same time scale. If data doesn't have a time attribute, post.period is indicated with indices.


Further arguments to adjust the default construction of the state-space model used for inference. One particularly important parameter is, which specifies our a priori knowledge about the volatility of the data. For even more control over the model, you can construct your own model using the bsts package and feed the fitted model into CausalImpact(), as shown in Example 3.


Instead of passing in data and having CausalImpact() construct a model, it is possible to create a custom model using the bsts package. In this case, omit data, pre.period, and post.period. Instead only pass in bsts.model, post.period.response, and alpha (optional). The model must have been fitted on data where the response variable was set to NA during the post-treatment period. The actual observed data during this period must then be passed to the function in post.period.response.


Actual observed data during the post-intervention period. This is required if and only if a fitted bsts.model is provided instead of data.


Desired tail-area probability for posterior intervals. Defaults to 0.05, which will produce central 95% intervals.


CausalImpact() returns a CausalImpact object containing the original observed response, its counterfactual predictions, as well as pointwise and cumulative impact estimates along with posterior credible intervals. Results can summarised using summary() and visualized using plot(). The object is a list with the following fields:

The field series is a zoo time-series object with the following columns:

response Observed response as supplied to CausalImpact().
cum.response Cumulative response during the modeling period.
point.pred Posterior mean of counterfactual predictions.
point.pred.lower Lower limit of a (1 - alpha) posterior interval.
point.pred.upper Upper limit of a (1 - alpha) posterior interval.
cum.pred Posterior cumulative counterfactual predictions.
cum.pred.lower Lower limit of a (1 - alpha) posterior interval.
cum.pred.upper Upper limit of a (1 - alpha) posterior interval.
point.effect Point-wise posterior causal effect.
point.effect.lower Lower limit of the posterior interval (as above).
point.effect.lower Upper limit of the posterior interval (as above).
cum.effect Posterior cumulative effect.
cum.effect.lower Lower limit of the posterior interval (as above).
cum.effect.upper Upper limit of the posterior interval (as above).


Optional arguments can be passed as a list in model.args, providing additional control over model construction:


Kay H. Brodersen


# Example 1
# Example analysis on a simple artificial dataset
# consisting of a response variable y and a
# single covariate x1.
x1 <- 100 + arima.sim(model = list(ar = 0.999), n = 52)
y <- 1.2 * x1 + rnorm(52)
y[41:52] <- y[41:52] + 10
data <- cbind(y, x1)
pre.period <- c(1, 40)
post.period <- c(41, 52)
impact <- CausalImpact(data, pre.period, post.period)

# Print and plot results
summary(impact, "report")
plot(impact, "original")
plot(impact$model$bsts.model, "coefficients")

# For further output, type:

## Not run: 
# Example 2
# Weekly time series: same data as in example 1, annotated
# with dates.
times <- seq.Date(as.Date("2016-01-03"), by = 7, length.out = 52)
data <- zoo(cbind(y, x1), times)

impact <- CausalImpact(data, times[pre.period], times[post.period])

summary(impact)  # Same as in example 1.
plot(impact)  # The plot now shows dates on the x-axis.

# Example 3
# For full flexibility, specify a custom model and pass the
# fitted model to CausalImpact(). To run this example, run
# the code for Example 1 first.
post.period.response <- y[post.period[1] : post.period[2]]
y[post.period[1] : post.period[2]] <- NA
ss <- AddLocalLevel(list(), y)
bsts.model <- bsts(y ~ x1, ss, niter = 1000)
impact <- CausalImpact(bsts.model = bsts.model,
                       post.period.response = post.period.response)

## End(Not run)

[Package CausalImpact version 1.3.0 Index]