不規則な時系列データの傾向


8

何十年にもわたって不規則な間隔で大きな水域から取られた水温測定のデータセットがあります。(興味がある場合は、テキサス州ガルベストンベイ)

データの先頭は次のとおりです。

  STATION_ID     DATE  TIME LATITUDE LONGITUDE YEAR MONTH DAY SEASON MEASUREMENT
1      13296  6/20/91 11:04 29.50889 -94.75806 1991     6  20 Summer        28.0
2      13296  3/17/92  9:30 29.50889 -94.75806 1992     3  17 Spring        20.1
3      13296  9/23/91 11:24 29.50889 -94.75806 1991     9  23   Fall        26.0
4      13296  9/23/91 11:24 29.50889 -94.75806 1991     9  23   Fall        26.0
5      13296  6/20/91 11:04 29.50889 -94.75806 1991     6  20 Summer        28.0
6      13296 12/17/91 10:15 29.50889 -94.75806 1991    12  17 Winter        13.0

(MEASUREMENTは対象の温度測定です。)

完全なセットはこちらから入手できます:https : //github.com/jscarlton/galvBayData/blob/master/gbtemp.csv

季節変動の影響を排除して、温度の傾向(ある場合)を経時的に観察します。時系列分解はこれを行うための最良の方法ですか?測定が定期的に行われなかったという事実をどのように処理しますか?このタイプの分析用のRパッケージがあることを願っていますが、PythonまたはStataでも問題ありません。 

(注:この分析では、測定値の空間変動を無視することを選択しています。理想的には、それも考慮に入れますが、そうすることは絶望的に複雑になると思います。)

回答:


18

時系列を明示的に分解するのではなく、データを時空間的にモデル化することをお勧めします。これは、以下に示すように、長期的な傾向は空間的に変化する可能性が高く、季節的な傾向は長期的な傾向によって変化するためです。そして空間的に。

一般化された加法モデル(GAM)は、あなたが説明するような不規則な時系列をフィッティングするのに適したモデルであることを発見しました。

以下に、次のフォームの完全なデータ用に準備したクイックモデルを示します

Ey=α+f1ToD+f2DoY+f+f4バツy+f5DoY+f6バツyToD+f7バツyDoY+f8バツy

どこ

  • α
  • f1ToD
  • f2DoY
  • f
  • f4バツy
  • f5DoY
  • f6バツyToD
  • f7バツyDoY
  • f8バツy

事実上、最初の4つのスムージングは​​、

  1. 時刻、
  2. シーズン、
  3. 長期的な傾向、
  4. 空間変動

残りの4つのテンソル積は、指定された共変量間の相互作用をモデル化しますが、モデルは

  1. 温度の季節パターンが時間とともにどのように変化するか、
  2. 時刻の効果が空間的にどのように変化するか、
  3. 季節効果が空間的にどのように変化するか、および
  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_ID13364の場合、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分未満で収まります。


0

decompose時系列をトレンド、季節性、ランダムの3つのコンポーネントに分ける関数を使用するだけです。結果からさまざまな値を抽出してプロットすることもできます。データを時系列として定義してください。関数stlは基本的に同じことを行いますが、データを分解する方法に柔軟性をもたらします。

次のウェブサイトもおすすめします

https://www.otexts.org/fpp/6

これは役に立ちますか?


答えてくれてありがとう。私は今ウェブサイトを見ています。課題はこれです。データが収集されなかった数か月間、またはシーズン全体でデータにギャップがあり、変化する時間枠に対処する方法を頭に浮かび上がらせることが難しくなっています。
griseus 2016年

0

1つのオプションは、データを継続的な基礎となる関数からの描画として扱う回帰戦略を使用することです(ここの説明を参照してください:不規則な間隔の時系列をモデル化するためのゴールドスタンダードはありますか?)。そこから、Singular Spectrum Analysisなどの方法を使用して信号を分解できます(Rの場合:https : //cran.r-project.org/web/packages/Rssa/index.html)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.