<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Time Series | Alex Baecher</title>
    <link>https://questlab.eco/tag/time-series/</link>
      <atom:link href="https://questlab.eco/tag/time-series/index.xml" rel="self" type="application/rss+xml" />
    <description>Time Series</description>
    <generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><copyright>© 2026 Alex Baecher</copyright><lastBuildDate>Fri, 12 Aug 2016 00:40:04 -0700</lastBuildDate>
    <image>
      <url>https://questlab.eco/media/icon_hu16270048066519736882.png</url>
      <title>Time Series</title>
      <link>https://questlab.eco/tag/time-series/</link>
    </image>
    
    <item>
      <title>Empirical Dynamic Models for Forecasting</title>
      <link>https://questlab.eco/post/edm-script/</link>
      <pubDate>Fri, 12 Aug 2016 00:40:04 -0700</pubDate>
      <guid>https://questlab.eco/post/edm-script/</guid>
      <description>&lt;h2 id=&#34;introduction-to-edms-for-forecasting-non-stationary-data&#34;&gt;Introduction to EDMs for Forecasting Non-stationary data&lt;/h2&gt;
&lt;p&gt;EDMs are a data-driven solution for uncovering hidden dynamic behavior in natural systems, which are often complex and dynamic (referred to as “non-stationarity” or “non-linearity”). This non-linearity means that the sign and magnitude of relationships within a system change with time, and therefore linear statistical approaches fail to properly represent such changes. Rather than assuming that the system is governed by any set of equations (i.e. unlike meteorological systems), EDMs reconstruct the dynamics of the system from time series data (hence “data-driven”) and provide a mechanistic understanding of the system. Under EDMs, the dynamics of a system are encoded in the temporal ordering of the time series, and the behavior of such a system can be explained by relating various states of a system using time lags (i.e. estimating the mathematical relationship of one variable at time $X(t)$, to the same variable at other times: $X(t+1)$ and $X(t+2)$. By relating states of a system using such lags, causal relationships between variables in the original system may be uncovered&amp;ndash;providing a number of ecologically relevant applications, including forecasting.&lt;/p&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34;
           src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/edm.gif&#34;
           loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;To reiterate, EDMs are driven by non-linear dynamics in a system (the
relationship of a variable, or state, at various time lags vary in sign
and magnitude). Taken’s theorem–the basis of EDM–states that an original
system’s dynamics can be reconstructed by exploiting the mathematical
relationships between historical records of a single variable. These
relationships can be mapped 1-to-1 using the Lorenz Attractor (also
known as the Butterfly attractor).&lt;/p&gt;
&lt;p&gt;

















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/edm2_hu12201909988955352687.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/edm2_hu15917479656847315141.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/edm2_hu11645103756732411621.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/edm2_hu12201909988955352687.webp&#34;
               width=&#34;596&#34;
               height=&#34;255&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

Tutorial on forecasting with stationary and non-stationary time series&lt;/p&gt;
&lt;h3 id=&#34;load-libraries&#34;&gt;Load libraries&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;library(astsa)
library(rEDM)
library(tidyverse)
library(forecast)
library(ggpubr)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;set-time-series-parameters-where-time--hrs-and-the-temporal-range-is-4-days&#34;&gt;Set time series parameters, where time = hrs and the temporal range is 4 days&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;set.seed(1)

time = 1:96
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;stationary-time-series&#34;&gt;Stationary time series&lt;/h1&gt;
&lt;h3 id=&#34;simulate-autocorrelated-timeseries-data-with-stationarity-linear-data-with-cyclical-autocorrelation-using-arimasim&#34;&gt;Simulate autocorrelated timeseries data with stationarity (linear data, with cyclical autocorrelation) using &lt;code&gt;arima.sim&lt;/code&gt;&lt;/h3&gt;
&lt;h4 id=&#34;arima-or-autoregressive-integrated-moving-average-models-necessarily-assume-linearity-because-they-rely-on-a-linear-relationship-to-predict-values-from-one-time-step-to-another&#34;&gt;Arima, or AutoRegressive Integrated Moving Average, models necessarily assume linearity, because they rely on a linear relationship to predict values from one time step to another.&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;stationary_y_arima &amp;lt;- arima.sim(n = length(time), list(ar = c(0.9, -0.8), ma = c(-0.41, 0.2)),
                                sd = sqrt(0.1))

df_ts &amp;lt;- data.frame(x = time, y = stationary_y_arima)

autoplot(stationary_y_arima) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-3-1_hu3923833573959093211.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-3-1_hu12773678633244539661.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-3-1_hu1549006150885248570.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-3-1_hu3923833573959093211.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;visualize-autocorrelation-structures-using-the-parial-autocorrelation-function-estimation-feature-in-the-forecast-package-function-acf&#34;&gt;Visualize autocorrelation structures using the Parial Autocorrelation Function Estimation feature in the &lt;code&gt;forecast&lt;/code&gt; package (function &lt;code&gt;acf()&lt;/code&gt;)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;acf(stationary_y_arima)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-1_hu17026907300735241105.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-1_hu8089632433936948208.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-1_hu13483225594687473385.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-1_hu17026907300735241105.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;pacf(stationary_y_arima)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-2_hu18364218191268249258.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-2_hu5088554948208542086.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-2_hu8134695697354690722.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-4-2_hu18364218191268249258.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;partition-data-into-training-and-predicting-subsets&#34;&gt;Partition data into training and predicting subsets:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;train &amp;lt;- 1:(length(time)/2)             # indices for the first 2/3 of the time series
&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&#34;arima-models-for-forecasting&#34;&gt;Arima models for forecasting:&lt;/h1&gt;
&lt;h3 id=&#34;run-a-standard-arima-model-with-no-lag-dependencies&#34;&gt;Run a standard Arima model, with no lag dependencies&lt;/h3&gt;
&lt;h4 id=&#34;this-model-is-mathematically-identical-to-a-intercept-only-linear-model&#34;&gt;This model is mathematically identical to a intercept only linear model:&lt;/h4&gt;
&lt;p&gt;$$\Large \hat{y}_t = \mu + \epsilon_{t}$$&lt;/p&gt;
&lt;h4 id=&#34;where-the-intercept-is-equal-to-the-mean-of-the-response-variable&#34;&gt;Where, the intercept is equal to the mean of the response variable:&lt;/h4&gt;
&lt;p&gt;$$\Large \mu = \frac{1}{n} \sum_{t=1}^{n} y_{t}$$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a &amp;lt;- Arima(stationary_y_arima[train])

#plot the fitted values from Arima model
autoplot(fitted(a), col = &amp;quot;blue&amp;quot;) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-6-1_hu152112157536712364.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-6-1_hu10389263712649820220.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-6-1_hu11313155472407154891.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-6-1_hu152112157536712364.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;perform-forecast-of-prediction-data-using-a-no-lag-arima-model&#34;&gt;Perform forecast of prediction data using a no-lag Arima model&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;autoplot(forecast(a, h = 48)) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-7-1_hu18391058151916765981.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-7-1_hu10895422997864652108.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-7-1_hu1228392626586771363.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-7-1_hu18391058151916765981.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;autoregressive-model-with-one-time-dependencyan-hourly-lag-term&#34;&gt;Autoregressive model, with one time dependency–an hourly lag term:&lt;/h3&gt;
&lt;p&gt;$$\Large \hat{y}_{t} = \mu + \phi_{1}y_{t-1} + \epsilon_{t}$$&lt;/p&gt;
&lt;p&gt;Where, $\Large \phi_1$ is a coefficient of lag&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a1 &amp;lt;- Arima(stationary_y_arima[train], c(1,0,0))

#plot the fitted values from Arima model
autoplot(fitted(a1), col = &amp;quot;blue&amp;quot;) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-1_hu527314919599288409.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-1_hu15020323914282561158.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-1_hu1676423677590565393.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-1_hu527314919599288409.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;#plot the forecasted values from Arima model
autoplot(forecast(a1, h = 48)) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-2_hu5957161691890017551.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-2_hu4208741386483684665.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-2_hu3657123997256001945.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-8-2_hu5957161691890017551.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;autoregressive-model-with-two-hourly-lags&#34;&gt;Autoregressive model, with two hourly lags:&lt;/h3&gt;
&lt;p&gt;$$\Large \hat{y}_{t} = \mu + \phi_{1}y_{t-1} + \phi_{2}y_{t-2} + \epsilon_{t}$$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a2 &amp;lt;- Arima(stationary_y_arima[train], c(1,0,0))

#plot the fitted values from Arima model
autoplot(fitted(a2), col = &amp;quot;blue&amp;quot;) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-1_hu527314919599288409.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-1_hu15020323914282561158.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-1_hu1676423677590565393.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-1_hu527314919599288409.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;#plot the forecasted values from Arima model
autoplot(forecast(a2, h = 48)) + geom_path(data = df_ts, aes(x = x, y = y)) + ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-2_hu5957161691890017551.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-2_hu4208741386483684665.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-2_hu3657123997256001945.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-9-2_hu5957161691890017551.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h4 id=&#34;autoregressive-models-with-up-to-5-hourly-lags&#34;&gt;Autoregressive models, with up to 5 hourly lags:&lt;/h4&gt;
&lt;p&gt;$$\Large \hat{y}_t = \mu + \phi_{1}y_{t-1} + [&amp;hellip;] + \phi_{5}y_{t-5} + \epsilon_{t}$$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a3 &amp;lt;- Arima(stationary_y_arima[train], c(3,0,0))
a4 &amp;lt;- Arima(stationary_y_arima[train], c(4,0,0))
a5 &amp;lt;- Arima(stationary_y_arima[train], c(5,0,0))

a1_gg &amp;lt;- autoplot(forecast(a3, h = 48)) + ggtitle(&amp;quot;Arima Model Forecast: 3 hourly lags&amp;quot;) +
  geom_path(data = df_ts, aes(x = x, y = y)) + 
  geom_path(aes(x = time[train], y = fitted(a3)[train]), col = &amp;quot;blue&amp;quot;) + 
   ylab(&amp;quot; &amp;quot;)

a2_gg &amp;lt;- autoplot(forecast(a4, h = 48)) + ggtitle(&amp;quot;Arima Model Forecast: 4 hourly lags&amp;quot;) +
  geom_path(data = df_ts, aes(x = x, y = y)) + 
  geom_path(aes(x = time[train], y = fitted(a4)[train]), col = &amp;quot;blue&amp;quot;) + 
   ylab(&amp;quot;Stationary Time Series&amp;quot;)

a3_gg &amp;lt;- autoplot(forecast(a5, h = 48)) + ggtitle(&amp;quot;Arima Model Forecast: 5 hourly lags&amp;quot;) +
  geom_path(data = df_ts, aes(x = x, y = y)) + 
  geom_path(aes(x = time[train], y = fitted(a5)[train]), col = &amp;quot;blue&amp;quot;) + 
   ylab(&amp;quot; &amp;quot;)

ggarrange(a1_gg, a2_gg, a3_gg, ncol = 1)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-10-1_hu17515598971010819387.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-10-1_hu8895741248900875675.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-10-1_hu18038795321176125581.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-10-1_hu17515598971010819387.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;now-we-can-move-into-models-with-different-cycle-structures-for-this-we-will-consider-half-day-lags-12-hr-periods&#34;&gt;Now, we can move into models with different cycle structures. For this, we will consider half day lags (12 hr periods)&lt;/h3&gt;
&lt;h4 id=&#34;autoregressive-models-with-an-hourly--and-half-day-time-dependency&#34;&gt;Autoregressive models, with an hourly- and half-day-time dependency:&lt;/h4&gt;
&lt;p&gt;$$\Large \hat{y}_t = \mu + \phi_{1}y_{t-1} + \phi_{2}y_{t-2} + \phi_{3}y_{t-3} + \phi_{4}y_{t-4} + \phi_{5}y_{t-12} + \epsilon_{t}$$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a41 &amp;lt;- Arima(stationary_y_arima[train], c(4,0,0), c(1,0,0))

autoplot(forecast(a41, h = 48)) + ggtitle(&amp;quot;Arima Model Forecast: 4 hourly cycle lag&amp;quot;) +
  geom_path(data = df_ts, aes(x = x, y = y)) + 
  geom_path(aes(x = time[train], y = fitted(a41)[train]), col = &amp;quot;blue&amp;quot;) +
  ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-11-1_hu9302860884111726051.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-11-1_hu8642984502335645233.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-11-1_hu10614276409159835171.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-11-1_hu9302860884111726051.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;now-we-will-let-the-arima-algorithm-choose-the-time-lag-parameters-using-autoarima&#34;&gt;Now, we will let the Arima algorithm choose the time lag parameters, using &lt;code&gt;auto.arima&lt;/code&gt;:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;aa &amp;lt;- auto.arima(stationary_y_arima[train])
summary(aa)

## Series: stationary_y_arima[train] 
## ARIMA(3,0,0) with zero mean 
## 
## Coefficients:
##          ar1      ar2      ar3
##       0.4728  -0.1068  -0.5655
## s.e.  0.1272   0.1513   0.1384
## 
## sigma^2 estimated as 0.08692:  log likelihood=-9.02
## AIC=26.04   AICc=26.97   BIC=33.52
## 
## Training set error measures:
##                      ME      RMSE       MAE      MPE     MAPE      MASE
## Training set 0.02152847 0.2854554 0.2289932 187.4472 335.9332 0.6855497
##                     ACF1
## Training set -0.06089878

# Auto-arima chose a 3-hour lag structure, with no half-day effects

autoplot(forecast(aa, h = 48)) + geom_path(data = df_ts, aes(x = x, y = y)) + 
  ylab(&amp;quot;Stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-12-1_hu10478963345962552179.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-12-1_hu10553494527365556019.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-12-1_hu6578880842138778313.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-12-1_hu10478963345962552179.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h1 id=&#34;non-stationary-time-series&#34;&gt;Non-stationary time series&lt;/h1&gt;
&lt;h3 id=&#34;now-we-will-simulate-non-linear-aka-non-stationary-data-where-relationships-change-through-time-using-diffinv&#34;&gt;Now we will simulate non-linear (a.k.a. non-stationary) data, where relationships change through time, using &lt;code&gt;diffinv&lt;/code&gt;:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;## non-stationary data
set.seed(44)
nonstationary_y &amp;lt;- diffinv(rnorm(length(time))) %&amp;gt;% ts()

autoplot(nonstationary_y) + ylab(&amp;quot;Non-stationary Time Series&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-13-1_hu8361590843094525608.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-13-1_hu18116198989023368975.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-13-1_hu13635102975722786926.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-13-1_hu8361590843094525608.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;lets-see-what-the-auto-arima-algorithm-estimates-with-non-stationary-data&#34;&gt;Let’s see what the auto Arima algorithm estimates with non-stationary data:&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;aa_ns &amp;lt;- auto.arima(nonstationary_y[train])

summary(aa_ns)

## Series: nonstationary_y[train] 
## ARIMA(0,1,0) 
## 
## sigma^2 estimated as 1.137:  log likelihood=-69.71
## AIC=141.42   AICc=141.51   BIC=143.27
## 
## Training set error measures:
##                      ME     RMSE       MAE       MPE     MAPE      MASE
## Training set 0.01182676 1.055224 0.7741009 0.9130602 36.00029 0.9791667
##                    ACF1
## Training set 0.08409507
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;now-visualize-forecast-of-a-linear-model-with-non-linear-data&#34;&gt;Now, visualize forecast of a linear model with non-linear data!&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;df_ts_st &amp;lt;- data.frame(x = time, y = nonstationary_y[1:96])

aa_ns &amp;lt;- autoplot(forecast(aa_ns, h = 48)) + 
  geom_path(data = df_ts_st, aes(x = x, y = y)) + 
  ylab(&amp;quot;Non-stationary Time Series&amp;quot;); aa_ns
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-15-1_hu2934379837407338171.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-15-1_hu15389575923361631140.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-15-1_hu13320879648571110662.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-15-1_hu2934379837407338171.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;not-a-very-good-prediction-lets-try-empirical-dynamic-models&#34;&gt;Not a very good prediction… Let’s try empirical dynamic models!&lt;/h3&gt;
&lt;h1 id=&#34;empirical-dynamic-models-for-forecasting&#34;&gt;Empirical Dynamic Models for forecasting:&lt;/h1&gt;
&lt;h3 id=&#34;the-model-is-a-system-of-three-ordinary-differential-equations-now-known-as-the-lorenz-equations&#34;&gt;The model is a system of three ordinary differential equations now known as the Lorenz equations:&lt;/h3&gt;
&lt;p&gt;$$\frac{dx}{dt} = \sigma(y - x)$$
$$\frac{dy}{dt} = x(p - x) - y$$
$$\frac{dz}{dt} = xy - \beta z$$&lt;/p&gt;
&lt;h3 id=&#34;we-will-use-the-simplex-function-to-determine-how-many-dimensions-time-lags-are-needed-to-effectively-develope-a-data-driven-mechanistic-formulation-of-the-time-series&#34;&gt;We will use the &lt;code&gt;simplex&lt;/code&gt; function to determine how many dimensions (time lags) are needed to effectively develope a data-driven mechanistic formulation of the time series&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# set data for historical record (library) and prediction
lib &amp;lt;- c(1, 48)
pred &amp;lt;- c(49, 96)

simplex_output &amp;lt;- simplex(nonstationary_y, lib, pred)
str(simplex_output)

## &#39;data.frame&#39;:    10 obs. of  16 variables:
##  $ E                  : int  1 2 3 4 5 6 7 8 9 10
##  $ tau                : num  1 1 1 1 1 1 1 1 1 1
##  $ tp                 : num  1 1 1 1 1 1 1 1 1 1
##  $ nn                 : num  2 3 4 5 6 7 8 9 10 11
##  $ num_pred           : num  47 46 45 44 43 42 41 40 39 38
##  $ rho                : num  0.768 0.796 0.682 0.716 0.515 ...
##  $ mae                : num  2.81 2.76 3.03 3.1 3.38 ...
##  $ rmse               : num  3.55 3.46 3.89 3.88 4.21 ...
##  $ perc               : num  0.979 0.978 1 1 1 ...
##  $ p_val              : num  7.73e-12 5.15e-13 3.37e-08 4.22e-09 1.56e-04 ...
##  $ const_pred_num_pred: num  47 46 45 44 43 42 41 40 39 38
##  $ const_pred_rho     : num  0.954 0.954 0.947 0.944 0.939 ...
##  $ const_pred_mae     : num  1.008 0.988 0.989 0.951 0.966 ...
##  $ const_pred_rmse    : num  1.23 1.21 1.22 1.17 1.18 ...
##  $ const_pred_perc    : num  0.979 0.978 0.978 1 1 ...
##  $ const_p_val        : num  8.26e-36 6.46e-35 1.10e-31 2.88e-30 3.02e-28 ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#34;lets-visualize-the-forecasting-skill-rho&#34;&gt;Let’s visualize the forecasting skill (rho)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;par(mar = c(4, 4, 1, 1), mgp = c(2.5, 1, 0))  # set margins for plotting
plot(simplex_output$E, simplex_output$rho, type = &amp;quot;l&amp;quot;, lwd = 5, col = &amp;quot;light blue&amp;quot;, xlab = &amp;quot;Embedding Dimension (E)&amp;quot;, 
     ylab = &amp;quot;Forecast Skill (rho)&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-1_hu4663220780974137972.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-1_hu8159935374829856186.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-1_hu4627458796794216504.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-1_hu4663220780974137972.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;simplex_output &amp;lt;- simplex(nonstationary_y, lib, pred, E = 2, tp = 1:10)
plot(simplex_output$tp, simplex_output$rho, type = &amp;quot;l&amp;quot;, lwd = 5, col = &amp;quot;light blue&amp;quot;, xlab = &amp;quot;Time to Prediction (tp)&amp;quot;, 
     ylab = &amp;quot;Forecast Skill (rho)&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-2_hu8614214833011827133.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-2_hu15716748166257607717.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-2_hu4956583592973100906.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-17-2_hu8614214833011827133.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 id=&#34;run-simplex-to-create-edm-model-for-forecasting&#34;&gt;Run &lt;code&gt;simplex&lt;/code&gt; to create EDM model for forecasting&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;smap_output &amp;lt;- simplex(nonstationary_y, lib, pred, E = 2, stats_only = FALSE)

predictions &amp;lt;- na.omit(smap_output$model_output[[1]])

df_ts_st_pred &amp;lt;- data.frame(x = time[51:96], y = nonstationary_y[51:96], predictions)

plot(df_ts_st$y~df_ts_st$x, type = &amp;quot;l&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-1_hu15449781592488315033.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-1_hu9112652997378736835.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-1_hu12806932964324019150.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-1_hu15449781592488315033.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;edm &amp;lt;- ggplot(data = df_ts_st_pred) + ggtitle(&amp;quot;Forecasts from EDM&amp;quot;) + xlab(&amp;quot;Time&amp;quot;) + ylab(&amp;quot; &amp;quot;) + 
  geom_ribbon(aes(x = x, y = y, ymin = y - 1.96*sqrt(pred_var), ymax = y +.96*sqrt(pred_var)), fill = &amp;quot;blue&amp;quot;, alpha = 0.2) +
  geom_ribbon(aes(x = x, y = y, ymin = y-sqrt(pred_var), ymax = y+sqrt(pred_var)), fill = &amp;quot;blue&amp;quot;, alpha = 0.4) + 
  geom_path(aes(x = x, y = y)) + 
  geom_path(data = df_ts_st, aes(x = x, y = y)) + 
  ylab(&amp;quot;Non-stationary Time Series&amp;quot;); edm
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34; &#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-2_hu6533135306713734512.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-2_hu9742329418107655175.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-2_hu6967299816902463539.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-2_hu6533135306713734512.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;ggarrange(aa_ns + coord_cartesian(ylim = c(-20,8)) + ggtitle(&amp;quot;Forecast with ARIMA&amp;quot;),
          edm + coord_cartesian(ylim = c(-20,8)) + ggtitle(&amp;quot;Forecast with EDM&amp;quot;)) + theme_bw()
&lt;/code&gt;&lt;/pre&gt;


















&lt;figure  id=&#34;figure-image-183&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Image 18.3&#34; srcset=&#34;
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-3_hu14727738865323504293.webp 400w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-3_hu10687812389112784535.webp 760w,
               /media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-3_hu12186086929266463582.webp 1200w&#34;
               src=&#34;https://questlab.eco/media/posts/edm_md_files/figure-markdown_strict/unnamed-chunk-18-3_hu14727738865323504293.webp&#34;
               width=&#34;672&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Image 18.3
    &lt;/figcaption&gt;&lt;/figure&gt;

&lt;pre&gt;&lt;code&gt;ggsave(&amp;quot;forecasts.jpeg&amp;quot;, dpi = 300)

## Saving 7 x 5 in image
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
  </channel>
</rss>
