Rの関数から ARMAtoMA {stats} を確認します。
関数 ARMAtoMA とは
ARMAtoMA は、ARMA(自己回帰移動平均)モデルの係数を、無限次MA(移動平均)モデルの係数(\(\psi\) ウェイト)に変換する関数です。
これは、時系列分析においてインパルス応答関数(Impulse Response Function)を求めることと同義です。
すなわち、ある時点 \(t\) で外部からのインパルス(ホワイトノイズ \(Z_t\))が 1単位発生した際、それが将来(\(t+1, t+2, \dots\))の時系列データにどのような影響を及ぼしていくかを表す係数列を計算します。
具体的には、ARMAモデル \(\phi(B)X_t = \theta(B)Z_t\) を、無限MA表現 \(X_t = \psi(B)Z_t\) (ただし \(\psi(B) = \theta(B)/\phi(B)\))に変換し、その係数 \(\psi_1, \psi_2, \dots, \psi_m\) を導出します。
なお、\(\psi_0\) は常に \(1\) であるため、この関数はラグ1以降の係数を返します。
関数 ARMAtoMA の引数
args(ARMAtoMA)function (ar = numeric(), ma = numeric(), lag.max)
NULL-
ar- AR(自己回帰)項の係数ベクトル(\(\phi_1, \phi_2, \dots, \phi_p\))。
- モデルの自己回帰部分を定義します。
- デフォルト:
numeric()(AR項なし)。
-
ma- MA(移動平均)項の係数ベクトル(\(\theta_1, \theta_2, \dots, \theta_q\))。
- モデルの移動平均部分を定義します。
- デフォルト:
numeric()(MA項なし)。
-
lag.max- 計算するラグの最大値(整数)。
- いくつの係数(\(\psi_1\) から \(\psi_{lag.max}\) まで)を計算するかを指定します。Cコード内の
mに相当します。 - 必須引数であり、デフォルト値はありません。正の整数を指定する必要があります。
シミュレーションコード
以下に、ARMAtoMA の機能を確認するためのシミュレーションコードを示します。
このシミュレーションでは、以下の手順を実行し、関数の挙動を検証します。
- ARMAモデルの設定:
- 具体的なAR係数とMA係数を設定します。
- ARMAtoMAによる計算:
- 関数を用いて理論的なインパルス応答(\(\psi\) ウェイト)を計算します。
- インパルス応答のシミュレーション:
- 時刻 \(t=1\) だけ値が \(1\) で、それ以外は \(0\) であるような「インパルス」データを作成します。
- このインパルスデータを、設定したARMAモデルのフィルタに通します(
filter関数を使用)。- 関数
filterは「入力データに対して、係数を掛け合わせながら足し合わせる計算(畳み込み、または再帰計算)」を行う関数です。
- 関数
- フィルタを通った後の出力結果が、
ARMAtoMAで計算された係数と一致することを確認します。
これにより、ARMAtoMA が「インパルスが時間の経過とともにどう伝播するか」を計算していることを確認できます。
# パッケージの読み込み
library(ggplot2)
# 1. ARMAモデルのパラメータ設定
# モデル: X_t = 0.7 * X_{t-1} - 0.2 * X_{t-2} + Z_t + 0.5 * Z_{t-1}
# AR(2) + MA(1) = ARMA(2, 1) モデル
ar_coef <- c(0.7, -0.2)
ma_coef <- c(0.5)
max_lag <- 15
cat("--- モデル設定 ---\n")
cat(sprintf("AR係数 (phi) : %s\n", paste(ar_coef, collapse = ", ")))
cat(sprintf("MA係数 (theta): %s\n", paste(ma_coef, collapse = ", ")))
cat(sprintf("計算ラグ数 : %d\n\n", max_lag))
# 2. ARMAtoMA を用いた係数計算
# これが理論的なインパルス応答係数(ラグ1~15)です
psi_weights <- ARMAtoMA(ar = ar_coef, ma = ma_coef, lag.max = max_lag)
cat("--- ARMAtoMAによる計算結果 (先頭5つを表示) ---\n")
print(head(psi_weights, 5))
cat("\n")
# 3. フィルタ関数を用いたシミュレーションによる検証
# インパルスデータの作成
# 時点1に「1」のインパルスを与え、その後は「0」が続くデータ
impulse_input <- c(1, rep(0, max_lag))
# 手順A: まずMA部分を適用 (Z_t + 0.5 * Z_{t-1})
# filter関数のsides=1は片側(過去のみ参照)フィルタを意味します
ma_filtered <- stats::filter(impulse_input,
filter = c(1, ma_coef),
method = "convolution", sides = 1
)
# NAを除去(最初の部分は計算できないためNAになりますが、ここでは先頭を補正)
# filterの挙動として、先頭の1はそのままで、次の項からMA係数が乗ります
# MA(1)なので、入力が(1,0,0...)なら、出力は(1, 0.5, 0...)となるはずです
# method="recursive"を使うARフィルタに入力する前の「MA変換済み入力」を作ります
ma_impulse <- c(1, ma_coef, rep(0, max_lag - length(ma_coef)))
# 手順B: 次にAR部分を適用 (再帰的フィルタ)
# これにより、無限に続く応答が生成されます
simulated_response <- stats::filter(ma_impulse,
filter = ar_coef,
method = "recursive"
)
# simulated_response の先頭はラグ0(値は1)なので、
# ARMAtoMAの結果(ラグ1以降)と比較するために2番目以降を取り出します
simulated_psi <- as.numeric(simulated_response)[2:(max_lag + 1)]
# 4. 結果の比較
df_compare <- data.frame(
Lag = 1:max_lag,
ARMAtoMA_Value = psi_weights,
Simulated_Value = simulated_psi
)
cat("--- シミュレーション(フィルタ)結果との比較 (先頭5つを表示) ---\n")
print(head(df_compare, 5))
cat("\n係数は全て一致しているか : ", all.equal(target = df_compare$ARMAtoMA_Value, current = df_compare$Simulated_Value))
# 5. 可視化
# インパルス応答関数のプロット
p1 <- ggplot(df_compare, aes(x = Lag)) +
# ゼロライン
geom_hline(yintercept = 0, color = "gray50") +
# ARMAtoMAの結果(赤い線と点)
geom_line(aes(y = ARMAtoMA_Value, color = "ARMAtoMA (理論値)"),
linewidth = 1
) +
geom_point(aes(y = ARMAtoMA_Value, color = "ARMAtoMA (理論値)"),
size = 3
) +
# シミュレーション結果(青い×印)を重ねて表示
geom_point(aes(y = Simulated_Value, color = "フィルタシミュレーション"),
shape = 4, size = 5, stroke = 1.5
) +
# 色の設定
scale_color_manual(
name = "",
values = c(
"ARMAtoMA (理論値)" = "firebrick",
"フィルタシミュレーション" = "blue"
)
) +
# ラベル設定
labs(
title = "ARMA(2,1)モデルのインパルス応答関数",
x = "ラグ (Lag)",
y = "係数値 (psi weights)"
) +
theme_minimal() +
theme(legend.position = "bottom")
print(p1)--- モデル設定 ---
AR係数 (phi) : 0.7, -0.2
MA係数 (theta): 0.5
計算ラグ数 : 15
--- ARMAtoMAによる計算結果 (先頭5つを表示) ---
[1] 1.20000 0.64000 0.20800 0.01760 -0.02928
--- シミュレーション(フィルタ)結果との比較 (先頭5つを表示) ---
Lag ARMAtoMA_Value Simulated_Value
1 1 1.20000 1.20000
2 2 0.64000 0.64000
3 3 0.20800 0.20800
4 4 0.01760 0.01760
5 5 -0.02928 -0.02928
係数は全て一致しているか : TRUEFigure 1 からAR項の影響により、初期のインパルスが徐々に減衰していく様子が見て取れます。
ARMAモデルの係数(ar, ma)だけを見ても、「過去のショックが現在にどう影響するか」を直感的に理解するのは困難ですが、ARMAtoMAを用いて変換することで、ショックの伝播プロセスを可視化・定量化することができます。
参照資料
- https://github.com/wch/r-source/blob/trunk/src/library/stats/src/pacf.c
- https://stackoverflow.com/questions/38495535/where-can-i-find-code-for-armatoma
以上です。

