CAUSALDISCOVERY Procedure
Getting Started: CAUSALDISCOVERY Procedure
This example illustrates how the CAUSALDISCOVERY procedure estimates the DAG from which the data are generated, in order to solve a seven-variable DAG structure learning problem.
The following DATA step produces the simulated data set to be used in the example:
data one;
input x1 - x7;
datalines;
0.6712068564 -0.2826079580 -0.5349256450 -0.8261341320
-3.0394109400 -1.8825135390 5.2510795861
-0.7107886740 -2.4798707050 1.2698001196 -6.2078732110
-14.3827270100 -11.0299665000 20.9643672460
... more lines ...
-0.5282917840 0.4435880321 -0.6905104940 0.4259155417
-0.1943036260 0.6881816788 -0.6409083280
-0.3955187900 -0.5117192740 -1.0742776010 0.7085965238
2.1642802138 1.5589762381 -2.7343111790
;
What is the relationship among these seven variables? That is the question that the DAG structure learning is trying to answer. Note that as the number of variables increases, the number of DAGs increases superexponentially. When the number of variables is seven, there are more than one billion seven-variable DAGs. Finding the one true DAG from which the data are generated is not easy. However, PROC CAUSALDISCOVERY might help you find that DAG in seconds or even less than a second.
The following DATA step loads the data set one into the data table one in your session that is associated with the mylib libref. The DATA step assumes that your libref is named mylib, but you can substitute any appropriately defined libref.
data mylib.one; set one; run;
The following code inputs the data set, specifies the variables, and names the output data table. The INITMETHOD=DATA option in the LEARN statement shows whether there is any difference between the topological order of the final estimated DAG and the order that is specified in the VAR statement.
proc causaldiscovery;
var x1 - x7;
learn data=mylib.one / initmethod=data out=mylib.oest;
run;
The number of observations is shown in Figure 1.
Figure 1: Number of Observations
| Number of Observations Read | 10000 |
|---|---|
| Number of Observations Used | 10000 |
The algorithm information is shown in Figure 2.
Figure 2: Algorithm Information
| Algorithm Information | |
|---|---|
| Algorithm | Topological Order Permutation |
| Initialization Method | Data |
| Maximum Iterations | 200 |
| Parallel | Yes |
| Seed | 1 |
The topological orders are shown in Figure 3. This table shows that there is a difference between the topological order of the final estimated DAG and the order that is specified in the VAR statement.
Figure 3: Initial and Final Topological Orders
| Topological Orders | ||
|---|---|---|
| Variable | Initial Order | Final Order |
| x1 | 1 | 1 |
| x2 | 2 | 3 |
| x3 | 3 | 2 |
| x4 | 4 | 4 |
| x5 | 5 | 6 |
| x6 | 6 | 5 |
| x7 | 7 | 7 |
The estimated full DAG that is expressed as the adjacency matrix is shown in Figure 4. In an adjacency matrix , element
is either 0 or 1. If
, this means that there is no edge from variable i to variable j; otherwise, there is an edge from variable i to variable j (that is, variable i is a parent of variable j, or variable j is a child of variable i).
Figure 4: Estimated Full Adjacency Matrix
| Estimated Full Adjacency Matrix | |||||||
|---|---|---|---|---|---|---|---|
| Variable | x1 | x2 | x3 | x4 | x5 | x6 | x7 |
| x1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
| x2 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
| x3 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
| x4 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
| x5 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
| x6 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
| x7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
The estimated DAG based on the significance level 0.0001% is shown in Figure 5.
Figure 5: Estimated Adjacency Matrices Based on the Significance Level 0.0001%
| Estimated Adjacency Matrices | ||||||||
|---|---|---|---|---|---|---|---|---|
| Alpha | Variable | x1 | x2 | x3 | x4 | x5 | x6 | x7 |
| 1E-6 | x1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| x2 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | |
| x3 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | |
| x4 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | |
| x5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
| x6 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | |
| x7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
As shown in the adjacency matrix in Figure 5, X1 and X3 have no parents; X2’s parents are X1 and X3; X4’s parents are X2 and X3; X5’s parents are X2 and X6; X6’s parents are X3 and X4; and X7’s parent is X6. Figure 6 shows this seven-variable DAG.
Figure 6: Estimated DAG

In fact, this estimated DAG is the true DAG for the data generating process, as shown in the following SAS code:
data one;
call streaminit('pcg', 12345);
x1 = 0; x2 = 0; x3 = 0; x4 = 0;
x5 = 0; x6 = 0; x7 = 0;
do i = 1 to 10000;
x1 = rand('Normal');
x3 = rand('Normal');
x2 = x1 - 0.5*x3 + rand('Normal');
x4 = 1.5*x2 - x3 + rand('Normal');
x6 = 0.5*x3 + 2*x4 + rand('Normal');
x5 = -x2 + 1.5*x6 + rand('Normal');
x7 = -2*x6 + rand('Normal');
output;
end;
drop i;
run;