Operations on time series
On this page
- How to add an operation
- Changing past values and adding future values
- Frequency conversion
- Weighted average
- Lag and lead
- Comparing different periods of the same series
- Aggregation
- Changes
- Converting values into indices
- Extracting the trend
- Extracting the cyclical component
- Seasonal adjustment (removing seasonal effects)
- Smoothing
- Arithmetic
- Other transformations
- Common errors
This section describes every MacroLens operation on time series (Technical Specification 2.11) with examples. Each operation can be applied in three ways:
- in the analysis workspace by selecting a series and choosing the operation from the menu (parameters are entered in a form);
- in the formula language — every operation has a function name (e.g.
yoy(s)); - through the Excel add-in when loading data with a transformation.
The results of all operations can be saved, shown in charts and tables and used in reports and presentations. The exact parameter lists and default values are given in the function reference.
How to add an operation
- In an analysis, select a series and click Add operation.
- Pick the operation from the grouped list or search it by name.
- Check or change the parameters (the defaults suit most cases) and confirm.
The operation is added at the end of the series' operation chain; the series description lists the steps applied (e.g. “frequency → Q (average); year-on-year change, %”). You can change or remove any step. Operations are applied in order, so their order matters.
Periods are written as follows everywhere: year 2024, half-year 2024-S2, quarter 2024-Q3, month 2024-07, week 2024-W27, day 2024-07-15. Frequencies: A annual, S semi-annual, Q quarterly, M monthly, W weekly, D daily.
Changing past values and adding future values
TS 2.11.1. With the series action Edit values, change any value or enter values for periods after the last observation (e.g. your own forecast for 2026–2027). A deleted value becomes missing. Edits apply only within the analysis, the database does not change, and the operation chain is applied to the edited data. See Analyses.
Frequency conversion
TS 2.11.2. Function convert(s, frequency, method).
Reducing the frequency (e.g. monthly → quarterly → annual):
| Method | Result | Suitable for |
|---|---|---|
average |
period average | levels and ratios: unemployment rate, price indices, interest rates |
sum |
period sum | flows: exports, GDP (EUR million), budget revenue |
last |
last value of the period | stocks at the end of the period: debt, population at year end |
first |
first value of the period | stocks at the beginning of the period |
max, min |
highest or lowest value | e.g. the highest monthly exchange rate in a year |
Increasing the frequency (e.g. annual → quarterly):
| Method | Result |
|---|---|
linear |
linear interpolation; the annual value is placed in the last sub-period (Q4) |
cubic |
smooth (cubic) interpolation |
constant |
the same value is repeated in every sub-period |
distribute |
the annual total is divided equally (e.g. an annual flow into quarterly flows) |
auto (default) chooses the method from the kind of indicator (its unit, title and dataset): flows (e.g. GDP, exports) are summed when reducing and distributed equally when increasing the frequency; end-of-period stocks (e.g. debt, deposits) take the last value (start-of-period stocks, e.g. the population at the beginning of the month, the first value) and are interpolated linearly when increasing; rates, indices, prices, exchange rates and anything unclear are averaged when reducing and interpolated linearly when increasing. The series history names the method applied (e.g. “sum; automatic: flow”); an explicitly chosen method is never changed. Incomplete periods (e.g. a quarter with only two months of data) are dropped unless you choose partial (the available values are then used).
Examples:
- Monthly unemployment rate: 2025-01 — 6.8; 2025-02 — 7.0; 2025-03 — 7.2.
convert(s, "Q", "average")→ 2025-Q1 = 7.0. - Monthly exports: 100; 110; 120 EUR million.
convert(s, "Q", "sum")→ 2025-Q1 = 330. - Annual value for 2024 — 400.
convert(s, "Q", "distribute")→ each quarter of 2024 = 100. - Annual values: 2023 — 100, 2024 — 104.
convert(s, "Q", "linear")→ 2024-Q1 = 101, Q2 = 102, Q3 = 103, Q4 = 104.
convert(s1, "A", "sum")
convert(s1, "Q", "last")
Weighted average
TS 2.11.3. wavg(s1, s2, …, weights=[w1, w2, …]) builds a series of the weighted average of several series. The series must have the same frequency (if not, convert the frequency first). With normalize on (default) the weights are divided by their sum, so weights [3, 1] mean 75 % and 25 %. The weights are constant numbers. If any of the series has no value for a period, the result for that period is missing (the weights of the other series are not re-scaled). Weights that change over time (e.g. GDP shares) are applied with a formula: (lt*gdp_lt + lv*gdp_lv) / (gdp_lt + gdp_lv).
Example: s1 = 2.0, s2 = 5.0, weights 0.6 and 0.4 → 0.6 × 2.0 + 0.4 × 5.0 = 3.2. With weights [3, 1]: (3 × 2.0 + 1 × 5.0) / 4 = 2.75.
wavg(lv, ee, pl, weights=[0.5, 0.3, 0.2])
This way you can calculate, for example, GDP growth of the main trading partners weighted by export shares.
Lag and lead
TS 2.11.4. lag(s, n) is the lag operator: the value at period t equals the original value at t − n. lead(s, n) is the lead operator: the value at t equals the original value at t + n. n is counted in periods of the series (for a quarterly series lag(s, 4) is one year).
| Period | s | lag(s, 1) | lead(s, 1) |
|---|---|---|---|
| 2024-Q1 | 100 | – | 102 |
| 2024-Q2 | 102 | 100 | 105 |
| 2024-Q3 | 105 | 102 | – |
Lags are often used in formulas:
s - lag(s, 4)— year-on-year absolute change for quarterly data;lead(pmi, 3)— the value of the indicator 3 months later (useful to check whether an indicator leads).
Comparing different periods of the same series
TS 2.11.5. There are several ways:
shiftyears(s, 1)moves the series one year forward on the time axis. With both the original and the shifted series in a chart you see this year's months against last year's.window(s, "2008-Q1", "2012-Q4")restricts the series to a chosen period. Several copies of the same series with different windows let you compare, e.g., two crises.- To compare the shape of periods, convert them to indices starting at the beginning of each period:
rebase(window(gdp, "2008-Q1", "2012-Q4"), "2008-Q1")
rebase(window(gdp, "2020-Q1", "2024-Q4"), "2020-Q1")
- The statistical analysis Period comparison shows the averages, standard deviations and average growth of the chosen periods side by side — see Statistical analysis.
Aggregation
TS 2.11.6.
| Function | Description | Example |
|---|---|---|
rolling(s, window, function) |
rolling sum, mean, minimum, maximum, median or standard deviation over the last window periods | rolling(s, 12, "sum") — 12-month sum |
cumulative(s, function, "year") |
cumulative sum (etc.) from the start of the series or from the start of each year | cumulative(s, "sum", "year") |
ytd(s, "sum") |
year-to-date sum or mean | ytd(budget, "sum") |
sum(s1, s2, …), mean(…), min(…), max(…) |
sum, mean, minimum or maximum of several series in each period | sum(exp_goods, exp_serv) |
Example: monthly budget revenue January–March — 10, 12, 11. cumulative(s, "sum", "year") → 10, 22, 33; the accumulation restarts in January of the next year.
In functions of several series, a missing value of any series gives a missing result by default; the skipna option calculates from the available values. A period sum or average (e.g. a quarterly sum of months) is obtained with frequency conversion.
Changes
TS 2.11.7.
| Function | Calculates |
|---|---|
mom(s) |
month-on-month change, % (monthly data only) |
qoq(s) |
quarter-on-quarter change, % (quarterly data; for monthly data the change over 3 months); annualize=true gives the annualised rate |
yoy(s) |
year-on-year change, % — compared with the same period of the previous year (any frequency) |
diff(s, n) |
absolute change over n periods |
logdiff(s, n) |
logarithmic change: 100 × (ln s(t) − ln s(t − n)) |
changeref(s, "2019-Q4", "pct") |
change relative to a chosen reference point (%, absolute, ratio or logarithmic) |
change(s, kind, horizon, n, annualize) |
generic change function: kind abs, pct, log, log_pct, ratio; horizon period, month, quarter, year or custom (n periods) |
Example (a quarterly index):
| Period | Value |
|---|---|
| 2019-Q4 | 95.0 |
| 2023-Q1 | 98.0 |
| 2023-Q4 | 100.0 |
| 2024-Q1 | 101.5 |
Results for 2024-Q1:
- quarter-on-quarter change
qoq(s): (101.5 / 100.0 − 1) × 100 = 1.50 %; - annualised quarter-on-quarter change
qoq(s, annualize=true): ((101.5 / 100.0)⁴ − 1) × 100 = 6.14 %; - year-on-year change
yoy(s): (101.5 / 98.0 − 1) × 100 = 3.57 %; - absolute change
diff(s, 1): 101.5 − 100.0 = 1.5; - logarithmic change
logdiff(s, 1): 100 × ln(101.5 / 100.0) = 1.49; - change relative to the reference point 2019-Q4
changeref(s, "2019-Q4", "pct"): (101.5 / 95.0 − 1) × 100 = 6.84 %.
Applying mom(s) to a non-monthly series shows an error — use qoq, yoy or change instead.
Converting values into indices
TS 2.11.8. rebase(s, base_start, base_end, value) calculates an index: value × s(t) / (mean of the series over the base period). The default base value is 100. If no base end is given, the base is a single period.
Example: quarterly values in 2015 — 78, 79, 81, 82 (mean 80). If the value in 2024-Q1 is 100, rebase(s, "2015-Q1", "2015-Q4") gives 100 × 100 / 80 = 125.0.
rebase(s, "2015")— annual data: 2015 = 100;rebase(s, "2015-Q1", "2015-Q4")— quarterly data: average of 2015 = 100;rebase(s, "2021-12", "", 1)— monthly data: December 2021 = 1.
Extracting the trend
TS 2.11.9. trend(s, method):
| Method | Trend |
|---|---|
linear |
linear trend (least squares) |
quadratic |
quadratic trend |
loglinear |
exponential (constant growth rate) trend |
hp |
Hodrick–Prescott trend (default) |
moving_average |
centred moving average (window periods) |
If not given, the Hodrick–Prescott parameter λ depends on the frequency: 100 for annual, 1600 for quarterly and 129,600 for monthly data. A larger λ gives a smoother trend.
The Hodrick–Prescott trend is less reliable at the last points of the series (“end-point problem”) and may change as new data arrives.
Extracting the cyclical component
TS 2.11.10. cycle(s, method) returns the cyclical component — the deviation of the series from its trend:
| Method | Description |
|---|---|
hp |
Hodrick–Prescott filter (default) |
bk |
Baxter–King band-pass filter: keeps fluctuations lasting from low to high years (default 1.5–8 years); k observations are lost at each end |
cf |
Christiano–Fitzgerald band-pass filter (same low/high), covers the whole sample |
hamilton |
Hamilton (2018) regression filter — an alternative to the HP filter without the end-point problem |
linear |
deviation from a linear trend |
output="pct" gives the percentage deviation from the trend (in logs); output="abs" (default) the absolute deviation.
Example — output gap: deviation of real (constant-price), seasonally adjusted GDP from its potential, %:
cycle(gdp_real, "hp", output="pct")
Use seasonally adjusted real series for cycle analysis.
Seasonal adjustment (removing seasonal effects)
TS 2.11.11. sa(s, method):
x13(default) — X-13ARIMA-SEATS, the US Census Bureau program used by many statistical agencies. MacroLens lets it choose the regARIMA model and detect outliers automatically and uses its X-11 decomposition (without trading-day adjustment); the SEATS decomposition and X-13's diagnostic tables (chosen ARIMA model, outliers, M and Q statistics) are not offered;stl— seasonal and trend decomposition using LOESS (STL);classical— classical decomposition with moving averages.
If X-13ARIMA-SEATS cannot be applied to a particular series (e.g. the series is too short), STL is used and this is stated clearly in the series' step description.
mode — multiplicative (seasonal swings proportional to the level; positive values only), additive or auto (chosen automatically). output — sa (seasonally adjusted series, default), seasonal (seasonal component), trend (trend-cycle component) or irregular (irregular component).
Applies to monthly and quarterly data. X-13ARIMA-SEATS needs at least three full years of data; in all cases at least two full years without gaps are required.
sa(s1)
sa(s1, "stl", output="seasonal")
If the source publishes an official seasonally adjusted series (SA or SCA in the metadata), it is usually better to use it. When new data arrives the seasonal factors are re-estimated, so earlier adjusted values may change slightly.
Smoothing
TS 2.11.12. smooth(s, method, …):
| Method | Description | Parameters |
|---|---|---|
ma |
moving average of the last window periods | window (default 3) |
centered_ma |
centred moving average | window |
ewma |
exponential smoothing | alpha (0–1; larger smooths less) |
loess |
local regression (LOESS) | frac — share of observations used (0–1) |
hp |
Hodrick–Prescott filter | lam |
henderson |
Henderson moving average (used in seasonal-adjustment programs) | window (odd, e.g. 13 for monthly) |
The Hodrick–Prescott filter on its own: hp(s, λ, "trend") or hp(s, λ, "cycle"). Common λ values: 100 (or 6.25) for annual data, 1600 for quarterly and 129,600 (or 14,400) for monthly data.
Example: values 4, 6, 8, 10. smooth(s, "ma", 3) → third period (4 + 6 + 8) / 3 = 6, fourth (6 + 8 + 10) / 3 = 8. The centred average smooth(s, "centered_ma", 3) gives 6 for the second period and 8 for the third.
Arithmetic
TS 2.11.13. With one series and a number:
| Function | Operation | In a formula |
|---|---|---|
add(s, 5), subtract(s, 5) |
add, subtract | s + 5, s - 5 |
multiply(s, 2), divide(s, 2) |
multiply, divide | s * 2, s / 2 |
power(s, 2) |
raise to a power | s ** 2 |
log(s), log10(s), exp(s) |
natural and common logarithm, exponential | |
abs(s), sqrt(s), negate(s), reciprocal(s) |
absolute value, square root, sign change, 1/s | -s, 1 / s |
round(s, 1) |
round to the given number of decimals | |
scale(s, 0.001, "EUR bn") |
multiply by a factor and change the unit |
Operations between several series are done with formulas, e.g. exports - imports or debt / gdp * 100. Values of the same period are combined.
Other transformations
fill(s, method)fills missing values:linear(linear interpolation),ffill(previous value),bfill(next value),zero;limit— the maximum number of consecutive missing values to fill.annualize(s, kind)expresses period values as annual rates:sum(default) multiplies by the number of periods per year (e.g. a quarterly flow × 4),compoundcompounds a percentage growth rate over a year, e.g.annualize(qoq(s), "compound").
Common errors
| Message | What to do |
|---|---|
| The series have different frequencies | Convert one series (convert) or set the analysis' common frequency |
| The operation does not apply to data of this frequency | E.g. mom only works on monthly data, seasonal adjustment on monthly and quarterly data |
| Too few observations | Use a longer period or another method |
| Invalid period | Use the format 2024, 2024-Q3, 2024-07, etc. |