本文へスキップ
からだにいいもの

まだ知らない、役に立つ情報を。ゲーム攻略・R・ガジェット

Rで解析:時系列のトレンドを線形フィルタで取り出す「rjd3filters」パッケージ

「rjd3filters」パッケージは、時系列データから線形フィルタでトレンドと循環成分を取り出すパッケージです。ヘンダーソン移動平均などのフィルタを作り、その係数やゲインを見比べてから、手元の時系列に当てることができます。系列の端、つまり先の観測値がまだ無い直近の時点でも、遅れを抑えたフィルタでトレンドを推計できます。渡すのは ts 形式の時系列で、季節調整済みの月次・四半期データを想定しています。JDemetra+ 3.x のJavaライブラリを使うため、Java 21 以上が必要です。景気や需要の転換点を早めに捉えたいときに役立てられるのではないかと考えます。

パッケージバージョンは2.4.0。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。事前に Java 21 以上をインストールしておく必要があります。

# パッケージのインストール
install.packages("rjd3filters")


# パッケージの読み込み
library("rjd3filters")
スポンサーリンク

コマンド例

詳細はコメント、パッケージのヘルプを確認してください。

線形フィルタ:前後の観測値に係数を掛けて足し合わせ、その時点の値を推計する方法。移動平均がその代表で、係数の並びがフィルタの性質を決めます。前後の観測値を同じ数ずつ使うものを対称フィルタ、先の観測値が足りない系列の端で使うものを非対称フィルタと呼びます。

ゲイン:周期ごとに、フィルタを通した後に変動がどれだけ残るかを表す値。トレンドを取り出すフィルタは、長い周期では1に近く、短い周期(ノイズ)では0に近いほど良いとされます。

以下では、京丹後市の月別宿泊者数指数(季節調整済みを想定した架空データ、2016年1月〜2025年12月)を使います。

# 乱数の種を固定する
set.seed(2026)


# 月数を指定する
n <- 120


# 経過月を作る
month_no <- 1:n


# 緩やかな増加と約4年周期の波に、月ごとのゆらぎを足す
tango <- 100 + 0.15 * month_no + 6 * sin(2 * pi * month_no / 48) + rnorm(n, sd = 2.5)


# 月次の時系列にする
tango <- ts(tango, start = c(2016, 1), frequency = 12)


# 先頭を確認する
head(tango)

単純移動平均の作成:simple_maコマンド

係数がすべて同じ移動平均を作ります。作った移動平均どうしは「+」「*」「/」「^」で組み合わせられるので、2×12項の中心化移動平均や3×3項の移動平均もそのまま作れます。

オプション意味初期値
order移動平均の項の数なし
lags移動平均で使う過去の観測値の数(負の整数で指定)-trunc((order – 1)/2)
# 3項の単純移動平均を作る
ma3 <- simple_ma(3, -1)
ma3

# 12項の移動平均を2つずらして平均し、2×12項の中心化移動平均を作る
m2x12 <- (simple_ma(12, -6) + simple_ma(12, -5)) / 2
m2x12

# 3項の移動平均を2回重ねて、3×3項の移動平均を作る
ma3^2

局所多項式フィルタの作成:lp_filterコマンド

局所多項式の当てはめに基づくフィルタを作ります。対称フィルタに加えて、先の観測値が0〜horizon個しか無いときの非対称フィルタもまとめて返します。kernel = “Henderson” で、季節調整で使われるヘンダーソン移動平均になります。

オプション意味初期値
horizon対称フィルタの片側の幅(項の数は2×horizon+1)6
degree当てはめる多項式の次数3
kernel使うカーネルc(“Henderson”, “Uniform”, “Biweight”, “Trapezoidal”, “Triweight”, “Tricube”, “Gaussian”, “Triangular”, “Parabolic”)
endpoints系列の端で使う非対称フィルタの作り方c(“LC”, “QL”, “CQ”, “CC”, “DAF”, “CN”)
icIC比(トレンドの変動に対するノイズの大きさの比)3.5
tweight遅れ(timeliness)の基準に掛ける重み0
passband遅れの基準で見る周波数の上限pi/12
# ヘンダーソン型の13項(horizon = 6)の局所多項式フィルタを作る
henderson <- lp_filter(horizon = 6, kernel = "Henderson", endpoints = "LC")
henderson

フィルタ係数のプロット:plot_coefコマンド

フィルタの係数をプロットします。q で、先の観測値をいくつ使えるときのフィルタを並べるかを選びます。

オプション意味初期値
xフィルタの係数、ゲインまたは位相なし
nxlab横軸の目盛りの数7
add前のプロットに重ねるかどうかFALSE
zero_as_na末尾の0の係数を取り除くか(TRUE)、そのままプロットするか(FALSE)TRUE
qプロットするフィルタ(使える先の観測値の数。q = horizon が対称フィルタ)0
legend凡例を表示するかどうかlength(q) > 1
legend.pos凡例の位置“topright”
…matplotコマンドに渡すその他のオプションなし
xlab横軸のラベル“”
ylab縦軸のラベル“coefficient”
# 先の観測値が0・3・6個のときの係数を並べてプロットする
plot_coef(henderson, q = c(0, 3, 6), legend = TRUE, lwd = 2)

ゲインのプロット:plot_gainコマンド

フィルタのゲインを周波数ごとにプロットします。横軸は0〜πの周波数で、左ほど長い周期です。

オプション意味初期値
xフィルタの係数、ゲインまたは位相なし
nxlab横軸の目盛りの数7
add前のプロットに重ねるかどうかFALSE
xlim横軸の範囲c(0, pi)
qプロットするフィルタ(使える先の観測値の数。q = horizon が対称フィルタ)0
legend凡例を表示するかどうかlength(q) > 1
legend.pos凡例の位置“topright”
nプロットに使う点の数101
…matplotコマンドに渡すその他のオプションなし
xlab横軸のラベル“”
ylab縦軸のラベル“gain”
# 直近の時点(q = 0)と対称フィルタ(q = 6)のゲインを比べる
plot_gain(henderson, q = c(0, 6), legend = TRUE, lwd = 2)

時系列データのフィルタリング:filterコマンド

作ったフィルタを時系列に当てます。非対称フィルタもまとめて渡すと、系列の端まで値が埋まります。読み込むと stats パッケージの filter コマンドを上書きする点に注意してください。

オプション意味初期値
x1変量または多変量の時系列なし
coefs対称フィルタと非対称フィルタの係数をまとめた行列またはリスト(対称フィルタから短いものの順)なし
remove_missingTRUEなら、フィルタを当てる前に先頭と末尾のNAを取り除くTRUE
# ヘンダーソン移動平均で宿泊者数指数のトレンドを取り出す
tango_trend <- filter(tango, henderson)

# 元の指数とトレンドを重ねてプロットする
plot(ts.union(tango, tango_trend),
  plot.type = "single",
  col = c("gray50", "red"), lwd = 2, ylab = "宿泊者数指数"
)

RKHSフィルタの作成:rkhs_filterコマンド

再生核ヒルベルト空間(RKHS)の考え方でフィルタを作ります。系列の端で使う非対称フィルタの幅を、asymmetricCriterion で選んだ基準が最も良くなるように決めます。

オプション意味初期値
horizon対称フィルタの片側の幅6
degree多項式の次数2
kernel使うカーネルc(“BiWeight”, “Henderson”, “Epanechnikov”, “Triangular”, “Uniform”, “TriWeight”)
asymmetricCriterion最適なバンド幅を決める基準。”Undefined”なら m+1 を使うc(“Timeliness”, “FrequencyResponse”, “Accuracy”, “Smoothness”, “Undefined”)
densityスペクトル密度の仮定。”uniform”(ホワイトノイズ)または”rw”(ランダムウォーク)c(“uniform”, “rw”)
passband基準で見る周波数の上限2 * pi/12
optimalbwバンド幅を最適化で選ぶかどうか。FALSEなら bandwidth の値を使うTRUE
optimal.minBandwidth最適なバンド幅を探す範囲の下限horizon
optimal.maxBandwidth最適なバンド幅を探す範囲の上限3 * horizon
bandwidthoptimalbw = FALSE のときに使うバンド幅horizon + 1
# 遅れ(Timeliness)を基準にRKHSフィルタを作る
rkhs <- rkhs_filter(horizon = 6, asymmetricCriterion = "Timeliness")

# ヘンダーソン移動平均と同じ q で係数をプロットして見比べる
plot_coef(rkhs, q = c(0, 3, 6), legend = TRUE, lwd = 2)

FSTフィルタの作成:fst_filterコマンド

忠実度(Fidelity)・滑らかさ(Smoothness)・遅れ(Timeliness)の3つの基準の重みを決めて、フィルタを1本作ります。lags と leads で、使う過去と先の観測値の数を決めます。

オプション意味初期値
lags使う過去の観測値の数(正の整数)6
leads使う先の観測値の数(0以上の整数)0
pdegree保つ局所多項式の最大の次数2
smoothness.weight滑らかさの基準の重み(0〜1)1
smoothness.degree滑らかさの基準の次数(ヘンダーソンは3)3
timeliness.weight遅れの基準の重み(0以上1未満)。smoothness.weight との和は0〜1にする0
timeliness.passband遅れの基準で位相のずれを見る周波数の上限(ラジアン)pi/6
timeliness.antiphase遅れを解析的に求めるか(TRUE)、数値的に求めるか(FALSE)TRUE
# 先の観測値を2つ使い、滑らかさと遅れを0.3ずつ重視したFSTフィルタを作る
fst2 <- fst_filter(lags = 6, leads = 2, smoothness.weight = 0.3, timeliness.weight = 0.3)
fst2

# 同じく先の観測値を2つ使うヘンダーソン移動平均と、トレンドの推計を比べる
fst_ma <- filter(tango, fst2)
lpp_ma <- filter(tango, henderson[, "q=2"])

# 元の指数と2つの推計を重ねてプロットする
plot(ts.union(tango, fst_ma, lpp_ma),
  plot.type = "single",
  col = c("gray50", "red", "blue"), lwd = 2, ylab = "宿泊者数指数"
)

トレンドの信頼区間の算出:confint_filterコマンド

フィルタで取り出したトレンドに信頼区間を付けます。結果は推定値・下限・上限の3列の時系列です。

オプション意味初期値
x対象の時系列なし
coef系列に当てる移動平均(moving_average)または有限フィルタ(finite_filters)なし
coef_var分散の推定(var_estimatorコマンド)に使う移動平均または有限フィルタ。既定は coef と同じcoef
level信頼水準0.95
asymmetric_varTRUEなら、対称フィルタの分散で代用せず、非対称フィルタごとに分散を推定するTRUE
gaussian_distributionTRUEなら正規分布、FALSEならt分布で信頼区間を求めるFALSE
exact_dfTRUEなら、t分布の自由度を厳密に求める(gaussian_distribution = FALSE のとき)。FALSEなら近似を使うTRUE
…coef を moving_average に変換するとき moving_averageコマンドに渡すその他のオプションなし
# ヘンダーソン移動平均で取り出したトレンドに90%信頼区間を付ける
tango_ci <- confint_filter(tango, henderson, level = 0.9)

# 直近の6か月を確認する
tail(tango_ci, 6)

# トレンドを実線、信頼区間を破線でプロットする
plot(tango_ci,
  plot.type = "single",
  col = c("red", "black", "black"), lty = c(1, 2, 2), lwd = 2,
  ylab = "宿泊者数指数"
)


この記事が誰かの役に立ちますように。

スポンサーリンク
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
当サイトに表示されている商品情報はAmazonから提供されたものであり、更新または削除される場合があります。
karada-goodはAmazonアソシエイトとして、適格販売により収入を得ています。