/* If you have SAS/IML 13.1 (SAS 9.4m1) or later, there are easier ways to create heat maps in SAS/IML. See http://blogs.sas.com/content/iml/2014/08/20/heat-map-in-sasiml.html and http://blogs.sas.com/content/iml/2014/09/29/discrete-heat-maps.html */ proc iml; k=5; /* number of repeated measurements */ s=9; /* number of individuals */ B = 1.4*j(k,k,1) + 2*I(k); /* compound symmetric matrix */ R = I(s) @ B; /* block-diagonal matrix */ print R; /* convert from wide to long format */ start WriteMatrixInLongForm(Y, DSName); Row = colvec( repeat(T(1:nrow(Y)), 1, ncol(Y)) ); /* row index */ Col = colvec( repeat(1:ncol(Y), nrow(Y)) ); /* col index */ X = colvec(Y); create (DSName) var {"Row" "Col" "X"}; /* SAS/IML 12.1 feature */ append; close (DSName); finish; *store module=WriteMatrixInLongForm; /* optional: store for later */ run WriteMatrixInLongForm(R, "BlockDiag"); X = hadamard(64); run WriteMatrixInLongForm(X, "Hadamard"); quit; proc print data=BlockDiag(obs=8); run; proc template; define statgraph HeatmapDisc; dynamic _X _Y _Z; begingraph; /* NOTE: Use the TYPE=DISCRETE statements if your version of SAS is before SAS 9.4m3 */ layout overlay / aspectratio=1 /* optional: for square matrices */ xaxisopts=( /* type=discrete */ discreteopts=(tickvaluefitpolicy=THIN) display=(line ticks tickvalues)) yaxisopts=( /* type=discrete */ discreteopts=(tickvaluefitpolicy=THIN) display=(line ticks tickvalues) reverse=true); heatmapparm x=_X y=_Y colorgroup=_Z / xbinaxis=false ybinaxis=false name="heatmap" primary=true display=ALL; discretelegend "heatmap"; endlayout; endgraph; end; run; ods graphics / height=800 width=800; title "Block Diagonal Correlation Matrix"; title2 "5 repeated measurements for 9 subjects"; proc sgrender data=BlockDiag template=HeatmapDisc; dynamic _X="col" _Y="row" _Z="X"; run; title "Hadamard(64) Matrix"; title2; proc sgrender data=Hadamard template=HeatmapDisc; dynamic _X="col" _Y="row" _Z="X"; run; footnote;title;title2;