DYNAMICLINEAR Procedure
Simultaneous Graphical Dynamic Linear Models
This example is designed to demonstrate the process of defining a simultaneous graphical dynamic linear model (SGDLM) within PROC DYNAMICLINEAR. SGDLMs, known for their advanced approach in handling dynamic, multivariate time series data, offer a robust framework for modeling complex interactions over time. For a deeper dive into the mechanics and applications of SGDLMs, including their unique strengths and how they can be effectively used in various scenarios, see the section Simultaneous Graphical Dynamic Linear Models.
The following DATA step loads the sample data:
data mylib.test_data;
input t MMDDYY10. y1 y2 y3 y4 y5 BEST12.;
format t MMDDYY10. y1 y2 y3 y4 y5 BEST12.;
datalines;
01/03/2002 1.158633277 -0.165838131 -0.220000432 0.08356095 0.097975091
01/04/2002 -0.995606401 -0.557778703 0.677071567 0.854087381 1.521078958
01/07/2002 1.494689626 1.200269513 -0.757267367 -0.468820299 1.558016222
01/08/2002 0.336831213 0.21765148 0.178311073 0.718694403 -1.277531854
01/09/2002 2.605081293 0.088138021 -0.95800973 -0.440623956 0.027367858
01/10/2002 1.365290757 0.207851726 -0.778749273 0.483102741 -0.259593807
01/11/2002 1.287939549 -0.625462152 -0.844034609 0.841906761 0.108750805
01/12/2002 -0.951405914 -0.272690273 -0.261733034 -2.068829141 0.671949044
01/13/2002 0.679413851 1.228575289 -0.840836877 1.124017627 0.185222142
01/14/2002 0.012315804 1.449826749 -0.424428315 -0.841630952 -0.431210039
;
Parental sets play a pivotal role in the structure and effectiveness of SGDLMs. According to Gruber and West (2016) and Gruber and West (2017), SGDLMs are adept at extracting correlations among time series, largely because of their sophisticated structural design that involves parental sets. For a more comprehensive understanding of parental sets, including their definition and importance in SGDLMs, see the sections PARENTALSET Statement and Parental Sets of Simultaneous Graphical Dynamic Linear Models. The following code produces the parental sets for the provided sample data, illustrating their configuration within the model:
data mylib.adj_table;
input ChildID ParentID;
datalines;
2 1
3 1
3 2
4 2
2 3
4 3
2 4
3 4
3 5
4 5
1 5
;
In SGDLMs, it is assumed that the observations adhere to a normal-gamma distribution, and their progression is tracked using the Kalman filter. PROC DYNAMICLINEAR offers multiple methods of defining the initial posterior distribution of these models. The following SAS code shows how to create input data tables that determine the initial means and covariances for SGDLMs. These tables are subsequently used in the INITIALDISTRIBUTION statement to set up the model’s initial state.
data mylib.init_mean;
input varname $1-4 varid parmname $24-40 parmid parmvalue;
datalines;
y1 1 Const 1 0.008596271
y1 1 ParSet_1 2 0.041964947
y1 1 ParSet_2 3 0.367778311
y2 2 Const 1 -0.004223895
y2 2 ParSet_1 2 -0.002395241
y2 2 ParSet_2 3 0.022385176
y3 3 Const 1 0.003904836
y3 3 ParSet_1 2 0.047429031
y3 3 ParSet_2 3 -0.489922549
y4 4 Const 1 -0.05762658
y4 4 ParSet_1 2 0.075128833
y4 4 ParSet_2 3 -0.224003793
y5 5 Const 1 -0.104497114
y5 5 ParSet_1 2 -2.129695978
y5 5 ParSet_2 3 0.047091226
y5 5 ParSet_3 4 -0.31115146
;
data mylib.init_cov;
input ParmValue_1 ParmValue_2 ParmValue_3 ParmValue_4 RowID;
datalines;
0.008068698 -0.000016642 -0.000191582 0 1
-0.000016642 0.040067528 -0.000022887 0 2
-0.000191582 -0.000022887 0.350903386 0 3
0.003999164 -6.19E-7 -3.51E-6 0 4
-6.19E-7 0.002287045 -6.4E-8 0 5
-3.51E-6 -6.4E-8 0.021373754 0 6
0.003699612 -8.63E-6 -0.000071039 0 7
-8.63E-6 0.04528632 -0.000021115 0 8
-0.000071039 -0.000021115 0.46764184 0 9
0.049313412 -0.000182135 -0.000713341 0 10
-0.000182135 0.07172781 -0.000022758 0 11
-0.000713341 -0.000022758 0.213791508 0 12
0.270791097 -0.001387886 -0.064982122 -0.019065019 13
-0.001387886 0.10090566 -0.000259538 -0.000076145 14
-0.064982122 -0.000259538 4.712605925 -0.003565199 15
-0.019065019 -0.000076145 -0.003565199 0.29606287 16
;
This initial setup is crucial, because it forms the foundation on which the model builds its subsequent forecasts and analyses. For a thorough understanding of how to configure the initial distribution in SGDLMs, see the section INITIALDISTRIBUTION Statement.
The INITIALDISTRIBUTION statement enables you to continue analyzing a previously saved SGDLM. This is particularly effective when you use it along with the OUTFILTERINFO= option in the FILTER statement. Together, these features allow for a seamless continuation of model analysis from a saved state, ensuring the integrity and consistency of the SGDLM’s progression over time.
DLMs use discount factors to regulate the proportion of state evolution error variance that is considered during the model’s evolution. For more information, see the section Discount Factors in Dynamic Linear Models. The following code shows how to use PROC DYNAMICLINEAR to fit an SGDLM to a given data set. In this example, the discount factors are defined using the DISCOUNTFACTOR statement.
proc dynamicLinear data=mylib.test_data;
id t;
model y1-y5;
parentalSet inAdjacency=mylib.adj_table;
filter out(percentiles=(2.5 50 97.5))=mylib.out_filter back=0;
forecast out(percentiles=(2.5 50 97.5))=mylib.out_forecast lead=3;
initialDistribution inMean=mylib.init_mean inCovariance=mylib.init_cov
shape=(positions=(1 2 5) values=(20 30 40));
discountFactor deltaGamma=(positions=(3 5) values=(0.997 0.998));
run;
Upon successful execution of the preceding code, you can review the model’s summary tables in Figure 1, which provides insight into the fit and performance of the SGDLM.
Figure 1: Model Summary
| Model Information | |
|---|---|
| Number of Variables Used | 5 |
| Simulation Size | 10000 |
| Random Number Seed | 12345 |
| Forecast Lead | 3 |
| Filter Back | 0 |
| Filter Lead | 1 |
| Number of Observations | 10 |
|---|---|
| Number of Observations Used | 10 |
| Input Tables | |||
|---|---|---|---|
| Name | Contents | Number of Rows | Number of Columns |
| TEST_DATA | Data | 10 | 6 |
| ADJ_TABLE | Adjacency Matrices | 11 | 2 |
| INIT_MEAN | Means | 16 | 5 |
| INIT_COV | Covariances (Full) | 16 | 5 |
| Output CAS Tables | |||
|---|---|---|---|
| CAS Library | Name | Number of Rows | Number of Columns |
| CASUSER(chuaxu) | OUT_FORECAST | 3 | 28 |
| CASUSER(chuaxu) | OUT_FILTER | 9 | 28 |
An example output of the forecasting results that the model generates is shown in Figure 2. The following PROC PRINT code prints the forecasting statistics that are generated by the OUT= option in the FORECAST statement:
proc print data=mylib.out_forecast;
run;
Figure 2: Example Output of Forecasting Results
| Obs | t | LeadStep | Mean_y1 | Variance_y1 | P2_5_y1 | P50_y1 | P97_5_y1 | Mean_y2 | Variance_y2 | P2_5_y2 | P50_y2 | P97_5_y2 | Mean_y3 | Variance_y3 | P2_5_y3 | P50_y3 | P97_5_y3 | Mean_y4 | Variance_y4 | P2_5_y4 | P50_y4 | P97_5_y4 | Mean_y5 | Variance_y5 | P2_5_y5 | P50_y5 | P97_5_y5 | RowID |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 01/14/2002 | 1 | 0.0562287843 | 1.6740409231 | -2.551030149 | 0.0617329767 | 2.5853554959 | 0.0030048896 | 0.2458605001 | -0.98092187 | 0.0012353502 | 0.9947060545 | -0.019379404 | 0.6742365123 | -1.63017889 | -0.021860637 | 1.6088152766 | 0.0249764176 | 0.9116031811 | -1.917011353 | 0.033318787 | 1.8836982077 | 0.3963792387 | 0.6318790441 | -1.128707987 | 0.3941573569 | 2.015804329 | 1 |
| 2 | 01/14/2002 | 2 | 0.051792414 | 1.689381942 | -2.631142191 | 0.0690782901 | 2.6253935528 | 0.0026459188 | 0.2477405635 | -0.975475003 | 0.0031644677 | 0.983248444 | -0.015777041 | 0.6780195983 | -1.638780493 | -0.019907368 | 1.6204697268 | 0.0278951803 | 0.9193195028 | -1.870895488 | 0.0331119637 | 1.8975615687 | 0.3953798175 | 0.6299070777 | -1.168920807 | 0.3929888396 | 1.9860243651 | 2 |
| 3 | 01/14/2002 | 3 | 0.0540313157 | 1.6909249168 | -2.604198531 | 0.062165089 | 2.6275629885 | 0.0027979918 | 0.2484346856 | -0.987649683 | 0.0006723175 | 1.0001381185 | -0.017778213 | 0.6803869184 | -1.653028696 | -0.019050342 | 1.6139603159 | 0.0239834421 | 0.9381107425 | -1.907374826 | 0.0305862902 | 1.9175205501 | 0.3980515611 | 0.6431627646 | -1.153080309 | 0.3955947084 | 2.0030555469 | 3 |
Additionally, an example of the filtering results that the model generates is shown in Figure 3. The following PROC PRINT code prints the first three observations of the forecasting statistics that are generated by the OUT= option in the FILTER statement:
proc print data=mylib.out_filter(obs=3);
run;
Figure 3: Example Output of Filtering Results
| Obs | t | LeadStep | Mean_y1 | Variance_y1 | P2_5_y1 | P50_y1 | P97_5_y1 | Mean_y2 | Variance_y2 | P2_5_y2 | P50_y2 | P97_5_y2 | Mean_y3 | Variance_y3 | P2_5_y3 | P50_y3 | P97_5_y3 | Mean_y4 | Variance_y4 | P2_5_y4 | P50_y4 | P97_5_y4 | Mean_y5 | Variance_y5 | P2_5_y5 | P50_y5 | P97_5_y5 | RowID |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 01/03/2002 | 1 | -0.054443041 | 855.25543349 | -3.049609881 | 0.0159366682 | 2.8734103027 | 0.1601617164 | 577.91896746 | -1.052842183 | -0.01847281 | 0.9765916156 | -1.644242541 | 50108.636773 | -4.496104256 | 0.0251924004 | 4.6038303985 | 0.9964143126 | 25474.95232 | -3.679928735 | -0.056030822 | 3.630336531 | -0.481015551 | 41789.705442 | -10.42614548 | -0.091581671 | 10.867644377 | 1 |
| 2 | 01/04/2002 | 1 | -0.265953197 | 415.77670547 | -2.158601034 | 0.032960854 | 2.2092917348 | -0.030385622 | 2.8241685107 | -0.997871327 | -0.020501244 | 0.9419312213 | 0.4069338608 | 1480.2701993 | -3.633721189 | 0.0148692715 | 3.3896686134 | -0.271851459 | 520.40410236 | -2.839657981 | -0.038934639 | 2.884275991 | -0.524440442 | 26815.660623 | -13.4860025 | 0.8797552241 | 14.731493133 | 2 |
| 3 | 01/07/2002 | 1 | -0.363511487 | 428.55045744 | -1.919494327 | 0.0009872112 | 1.9481959368 | -0.064543628 | 28.362208296 | -0.920294573 | -0.032285013 | 0.8703851427 | 0.4065960356 | 647.68497031 | -2.075284273 | 0.0086831118 | 2.164646309 | 0.1948211869 | 675.7931971 | -1.908574062 | 0.0347232143 | 2.0284860639 | 0.7692750656 | 1807.6712956 | -3.121739776 | 1.1222731888 | 5.5148719972 | 3 |
The following SAS code is designed to create a visual representation of the empirical confidence interval for the variable y1. An empirical confidence interval offers an estimate of the range within which you expect to find the true value of y1 a certain percentage of the time, according to the sample data. This code produces a plot that showcases the variability of y1, with the empirical confidence interval demarcated, thus providing a visual assessment of the precision of y1’s estimated values within the model. The results are shown in Figure 4.
data y1_comb;
format t MMDDYY10. Mean_y1 P2_5_y1 P50_y1 P97_5_y1 Best12.;
set mylib.out_filter(keep=Mean_y1 P2_5_y1 P50_y1 P97_5_y1);
set mylib.test_data(keep=t y1 where=(t>'03Jan2002'd));
run;
proc sort data=y1_comb;
by t;
run;
proc sgplot data=y1_comb;
band x=t upper=P2_5_y1 lower=P97_5_y1 / transparency=.3
legendlabel='95% Empirical C.I.s';
series x=t y=y1 / legendlabel='Actual Values of y1'
markers markerattrs=(color=red size=5 symbol=circlefilled)
lineattrs=(color=red pattern=shortdash);
series x=t y=Mean_y1 / legendlabel='Mean_y1'
markers markerattrs=(color=blue size=5 symbol=triangle)
lineattrs=(color=blue pattern=solid);
series x=t y=P50_y1 / legendlabel='Median_y1'
markers markerattrs=(color=cyan size=5 symbol=circle)
lineattrs=(color=cyan pattern=solid);
label t="Date" y1="Values";
run;
Figure 4: Empirical Confidence Intervals of Variable y1

The prior example demonstrates how to specify parental sets, initial distributions, and discount factors in PROC DYNAMICLINEAR. It is important to note that these statements are optional, offering flexibility according to the user’s needs and expertise. Additionally, for generating plots of confidence intervals, the data that are specified in the OUT= option of the FILTER statement are essential.
PROC DYNAMICLINEAR is designed with a high degree of flexibility to cater to a wide range of users. This includes those who are primarily interested in forecasting outcomes but might not have extensive knowledge of model configuration. For such users, a simpler and more concise code setup can be just as effective. The following code is an example of such a streamlined configuration, which is aimed at maximizing ease of use and accessibility:
proc dynamicLinear data=mylib.test_data;
id t;
model y1-y5;
parentalSet inAdjacency=mylib.adj_table;
forecast out=mylib.out_forecast lead=3;
run;
This simplified approach enables users to take advantage of the powerful forecasting capabilities of PROC DYNAMICLINEAR without the need to delve into more complex configuration details.