時系列を明示的に分解するのではなく、データを時空間的にモデル化することをお勧めします。これは、以下に示すように、長期的な傾向は空間的に変化する可能性が高く、季節的な傾向は長期的な傾向によって変化するためです。そして空間的に。
一般化された加法モデル(GAM)は、あなたが説明するような不規則な時系列をフィッティングするのに適したモデルであることを発見しました。
以下に、次のフォームの完全なデータ用に準備したクイックモデルを示します
E( y私)= α + f1(ToD私)+ f2(DoY私)+ f3(年私)+ f4(x私、y私)+f5(DoY私、年私)+ f6(x私、y私、ToD私)+f7(x私、y私、DoY私)+ f8(x私、y私、年私)
どこ
- α
- f1(ToD私)
- f2(DoY私)
- f3(年私)
- f4(x私、y私)
- f5(DoY私、年私)
- f6(x私、y私、ToD私)
- f7(x私、y私、DoY私)
- f8(x私、y私、年私
事実上、最初の4つのスムージングは、
- 時刻、
- シーズン、
- 長期的な傾向、
- 空間変動
残りの4つのテンソル積は、指定された共変量間の相互作用をモデル化しますが、モデルは
- 温度の季節パターンが時間とともにどのように変化するか、
- 時刻の効果が空間的にどのように変化するか、
- 季節効果が空間的にどのように変化するか、および
- 長期的な傾向が空間的にどのように変化するか
データはRにロードされ、次のコードで少しマッサージされます
library('mgcv')
library('ggplot2')
library('viridis')
theme_set(theme_bw())
library('gganimate')
galveston <- read.csv('gbtemp.csv')
galveston <- transform(galveston,
datetime = as.POSIXct(paste(DATE, TIME),
format = '%m/%d/%y %H:%M', tz = "CDT"))
galveston <- transform(galveston,
STATION_ID = factor(STATION_ID),
DoY = as.numeric(format(datetime, format = '%j')),
ToD = as.numeric(format(datetime, format = '%H')) +
(as.numeric(format(datetime, format = '%M')) / 60))
モデル自体は、bam()
GAMをこのような大きなデータセットに適合させるために設計された関数を使用して適合されます。gam()
このモデルにも使用できますが、フィットするまでに少し時間がかかります。
knots <- list(DoY = c(0.5, 366.5))
M <- list(c(1, 0.5), NA)
m <- bam(MEASUREMENT ~
s(ToD, k = 10) +
s(DoY, k = 30, bs = 'cc') +
s(YEAR, k = 30) +
s(LONGITUDE, LATITUDE, k = 100, bs = 'ds', m = c(1, 0.5)) +
ti(DoY, YEAR, bs = c('cc', 'tp'), k = c(15, 15)) +
ti(LONGITUDE, LATITUDE, ToD, d = c(2,1), bs = c('ds','tp'),
m = M, k = c(20, 10)) +
ti(LONGITUDE, LATITUDE, DoY, d = c(2,1), bs = c('ds','cc'),
m = M, k = c(25, 15)) +
ti(LONGITUDE, LATITUDE, YEAR, d = c(2,1), bs = c('ds','tp'),
m = M), k = c(25, 15)),
data = galveston, method = 'fREML', knots = knots,
nthreads = 4, discrete = TRUE)
s()
一方で用語は、主効果あるti()
の用語はテンソル積されている相互作用という名前の共変量の主効果が基礎から削除された滑らかにします。これらのti()
スムージングは、記述された変数の相互作用を数値的に安定した方法で含める方法です。
knots
私たちは、12月31日夜11時59分は、0:01月1日とスムーズにまで参加したい-オブジェクトはちょうど私が今年効果の日のために使用スムーズ巡回のエンドポイントを設定しています。これは、うるう年をある程度説明します。
モデルの要約は、これらすべての影響が重要であることを示しています。
> summary(m)
Family: gaussian
Link function: identity
Formula:
MEASUREMENT ~ s(ToD, k = 10) + s(DoY, k = 12, bs = "cc") + s(YEAR,
k = 30) + s(LONGITUDE, LATITUDE, k = 100, bs = "ds", m = c(1,
0.5)) + ti(DoY, YEAR, bs = c("cc", "tp"), k = c(12, 15)) +
ti(LONGITUDE, LATITUDE, ToD, d = c(2, 1), bs = c("ds", "tp"),
m = list(c(1, 0.5), NA), k = c(20, 10)) + ti(LONGITUDE,
LATITUDE, DoY, d = c(2, 1), bs = c("ds", "cc"), m = list(c(1,
0.5), NA), k = c(25, 12)) + ti(LONGITUDE, LATITUDE, YEAR,
d = c(2, 1), bs = c("ds", "tp"), m = list(c(1, 0.5), NA),
k = c(25, 15))
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 21.75561 0.07508 289.8 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(ToD) 3.036 3.696 5.956 0.000189 ***
s(DoY) 9.580 10.000 3520.098 < 2e-16 ***
s(YEAR) 27.979 28.736 59.282 < 2e-16 ***
s(LONGITUDE,LATITUDE) 54.555 99.000 4.765 < 2e-16 ***
ti(DoY,YEAR) 131.317 140.000 34.592 < 2e-16 ***
ti(ToD,LONGITUDE,LATITUDE) 42.805 171.000 0.880 < 2e-16 ***
ti(DoY,LONGITUDE,LATITUDE) 83.277 240.000 1.225 < 2e-16 ***
ti(YEAR,LONGITUDE,LATITUDE) 84.862 329.000 1.101 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.94 Deviance explained = 94.2%
fREML = 29807 Scale est. = 2.6318 n = 15276
ti()
F
ただし、簡単なチェックとして、3つの空間ti()
スムース(m.sub
)を削除すると、AICによって評価されるフィットが大幅に低下します。
> AIC(m, m.sub)
df AIC
m 447.5680 58583.81
m.sub 239.7336 59197.05
plot()
メソッドを使用して、最初の5つのスムースの部分効果をプロットできます。3Dテンソル積のスムースは、デフォルトでは簡単にプロットできません。
plot(m, pages = 1, scheme = 2, shade = TRUE, scale = 0)
scale = 0
そこでの議論は、すべてのプロットを独自のスケールに置き、効果の大きさを比較するために、これをオフにすることができます:
plot(m, pages = 1, scheme = 2, shade = TRUE)
これで、季節効果が支配的になっていることがわかります。長期的な傾向(平均)が右上のプロットに表示されます。ただし、長期的な傾向を実際に見るには、測点を選択して、その測点のモデルから予測し、時刻と曜日をいくつかの代表的な値(正午、夏の1日のうちの1日)に固定する必要があります。いう)。シリーズの最初の1年か2年には、残りのレコードに比べていくつかの低温値があり、これはを含むすべてのスムージングでピックアップされている可能性がありYEAR
ます。これらのデータは、より詳しく調べる必要があります。
これは実際にはそのための場所ではありませんが、ここではモデルフィットのいくつかの視覚化を示します。最初に、温度の空間パターンと、それがシリーズの長年にわたってどのように変化するかを調べます。それを行うために、毎年180日目の正午に、空間ドメイン上の100x100グリッドのモデルから予測します。
pdata <- with(galveston,
expand.grid(ToD = 12,
DoY = 180,
YEAR = seq(min(YEAR), max(YEAR), by = 1),
LONGITUDE = seq(min(LONGITUDE), max(LONGITUDE), length = 100),
LATITUDE = seq(min(LATITUDE), max(LATITUDE), length = 100)))
fit <- predict(m, pdata)
次に、観測値からある程度離れているすべてのデータポイントのNA
予測値を欠落、に設定しましたfit
(比例dist
)。
ind <- exclude.too.far(pdata$LONGITUDE, pdata$LATITUDE,
galveston$LONGITUDE, galveston$LATITUDE, dist = 0.1)
fit[ind] <- NA
予測を予測データに結合します
pred <- cbind(pdata, Fitted = fit)
NA
このように予測値を設定すると、データのサポートを超えて外挿することができなくなります。
ggplot2の使用
ggplot(pred, aes(x = LONGITUDE, y = LATITUDE)) +
geom_raster(aes(fill = Fitted)) + facet_wrap(~ YEAR, ncol = 12) +
scale_fill_viridis(name = expression(degree*C), option = 'plasma',
na.value = 'transparent') +
coord_quickmap() +
theme(legend.position = 'top', legend.key.width = unit(2, 'cm'))
以下を取得します
プロットをファセットするのではなくアニメーション化すると、温度の年々の変動をもう少し詳しく見ることができます
p <- ggplot(pred, aes(x = LONGITUDE, y = LATITUDE, frame = YEAR)) +
geom_raster(aes(fill = Fitted)) +
scale_fill_viridis(name = expression(degree*C), option = 'plasma',
na.value = 'transparent') +
coord_quickmap() +
theme(legend.position = 'top', legend.key.width = unit(2, 'cm'))+
labs(x = 'Longitude', y = 'Latitude')
gganimate(p, 'galveston.gif', interval = .2, ani.width = 500, ani.height = 800)
長期トレンドをより詳細に見るために、特定のステーションを予測できます。たとえば、STATION_ID
13364の場合、4つの四半期の日数を予測するには、次を使用して、予測する共変量の値を準備します(正午、1年目の1日、90、180、および270、選択した測点で) 、および500の等間隔値での長期トレンドの評価)
pdata <- with(galveston,
expand.grid(ToD = 12,
DoY = c(1, 90, 180, 270),
YEAR = seq(min(YEAR), max(YEAR), length = 500),
LONGITUDE = -94.8751,
LATITUDE = 29.50866))
次に、標準誤差を予測して求め、おおよその点ごとの95%信頼区間を形成します。
fit <- data.frame(predict(m, newdata = pdata, se.fit = TRUE))
fit <- transform(fit, upper = fit + (2 * se.fit), lower = fit - (2 * se.fit))
pred <- cbind(pdata, fit)
私たちはそれをプロットします
ggplot(pred, aes(x = YEAR, y = fit, group = factor(DoY))) +
geom_ribbon(aes(ymin = lower, ymax = upper), fill = 'grey', alpha = 0.5) +
geom_line() + facet_wrap(~ DoY, scales = 'free_y') +
labs(x = NULL, y = expression(Temperature ~ (degree * C)))
生産
明らかに、これらのデータのモデル化には、ここに示すもの以外にも多くのことがあり、残余の自己相関とスプラインの過剰適合をチェックしたいと思いますが、データの機能のモデル化の1つがより詳細な傾向の調査。
もちろんSTATION_ID
、それぞれを個別にモデル化することもできますが、その場合はデータが破棄され、多くの観測所には観測がほとんどありません。ここで、モデルはすべての測点情報を借用してギャップを埋め、関心のある傾向の推定を支援します。
いくつかの注意事項 bam()
bam()
このモデルは、すべての使用しているmgcv迅速(複数のスレッドモデルを推定するためのトリックを4)、速いREML平滑選択(method = 'fREML'
)、および共変量の離散化を。これらのオプションをオンにすると、モデルは、64GbのRAMを搭載した2013年のデュアル4コアXeonワークステーションに1分未満で収まります。