FOCUS AREAS

Graphics

stacked graphs
Base SAS: Graph Template Language

%let gpath='.';
%let dpi=100;

/* Generate some simulated data */
data sines;
  do i=0 to 160;
    f1 = sin(0.025*i) - 1.5*cos(0.09*i + 5) + 0.6*sin(0.08*i + 19);
    f2 = 3*sin(0.02*i + 20) - 1.3*sin(0.005*i+10);
    f3 = 2*sin(0.04*i - 8) + 0.05*i;
    f4 = 0.8*cos(0.03*i-8) + 3*sin(0.02*i+17);
    f5 = 2*cos(0.04*i + 13) + 0.02*abs(i - 77);
    f6 = 2*sin(0.027*i + 3) + sin(0.018*i);

    f1 = abs(f1); f2 = abs(f2); f3 = abs(f3)/1.3;
    f4 = abs(f4); f5 = abs(f5); f6 = abs(f6);
    if f1 < 0.1 then f1 = 0;
    if f4 < 0.1 then f4 = 0;

    format time monYY.;
    time = '01Jan1970'd + i;

    output;
  end;
run;

data sines_stack;
  set sines;
  b1L = 0;
  b1U = b1L + f1;
  b2L = b1U;
  b2U = b2L + f2;
  b3L = b2U;
  b3U = b3L + f3;
  b4L = b3U;
  b4U = b4L + f4;
  b5L = b4U;
  b5U = b5L + f5;
  b6L = b5U;
  b6U = b6L + f6;

  drop f1 f2 f3 f4 f5 f6;
run;
 
data sines_river;
  set sines;
  /* G0 = - 1/2 * sigma[1..n](Fi) */
  b1L = -0.5*(f1 + f2 + f3 + f4 + f5 + f6);
  b1U = b1L + f1;
  b2L = b1U;
  b2U = b2L + f2;
  b3L = b2U;
  b3U = b3L + f3;
  b4L = b3U;
  b4U = b4L + f4;
  b5L = b4U;
  b5U = b5L + f5;
  b6L = b5U;
  b6U = b6L + f6;

  length label $35;
  if i = 45 then
  do; ly = 0.5*(b1L + b1U); label="VOCs"; end;
  else if i=36 then
  do; ly = 0.5*(b2L + b2U ); label="Nitrogen Oxides"; end;
  else if i=80 then
  do; ly = 0.5*(b3L + b3U); label="Carbon Monoxide"; end;
  else if i=47 then
  do; ly = 0.5*(b4L + b4U); label="Sulfur Dioxide"; end;
  else if i=130 then
  do; ly = 0.5*(b5L + b5U); label="Particulate 1"; end;
  else if i=55 then
  do; ly = 0.5*(b6L + b6U); label="Particulate 2"; end;
  else
  do; ly = .; label=" "; end;

  drop f1 f2 f3 f4 f5 f6;
run;

/* Minimized Deviation */
data sines_river_mindev;
  set sines;
  /* G0 = - 1/(n+1) * sigma[1..n]((n - i + 1)* Fi) */
  b1L = -0.14*(6*f1 + 5*f2 + 4*f3 + 3*f4 + 2*f5 + 1*f6);
  b1U = b1L + f1;
  b2L = b1U;
  b2U = b2L + f2;
  b3L = b2U;
  b3U = b3L + f3;
  b4L = b3U;
  b4U = b4L + f4;
  b5L = b4U;
  b5U = b5L + f5;
  b6L = b5U;
  b6U = b6L + f6;

  length label $35;
  if i = 45 then
   do; ly = 0.5*(b1L + b1U); label="VOCs"; end;
  else if i=36 then
   do; ly = 0.5*(b2L + b2U ); label="Nitrogen Oxides"; end;
  else if i=80 then
   do;ly = 0.5*(b3L + b3U); label="Carbon Monoxide"; end;
  else if i=47 then
   do; ly = 0.5*(b4L + b4U); label="Sulfur Dioxide"; end;
  else if i=130 then
   do; ly = 0.5*(b5L + b5U); label="Particulate 1"; end;
  else if i=58 then
   do; ly = 0.5*(b6L + b6U); label="Particulate 2"; end;
  else
   do; ly = .; label=" "; end;

  drop f1 f2 f3 f4 f5 f6;
run;

/* Stacked Graphs. Byron L., Wattenberg M. IEEE InfoVis 2008 */
proc template;                                                                
  define statgraph river;
    dynamic dynTime "time" 
      dynLL1 "first lower limit" dynLU1 "first upper limit"
      dynLL2 dynLU2 dynLL3 dynLU3 dynLL4 dynLU4 dynLL5 dynLU5 dynLL6 dynLU6
      dynTitle dynFootNote;
    begingraph / designWidth=7in designHeight=4.5in;   
      EntryTitle dynTitle; 
      layout overlay / cycleAttrs=true
        xaxisopts=(offsetMin=0 offsetMax=0 label="Date" display=(line ticks tickvalues)
          timeopts=(minorTicks=true interval=month tickvalueformat=monyy.))
        yaxisOpts=(display=(line label) 
          label="Proportion of Air Pollutants");
%let dispFillAttrs = dataTransparency=0.5;
        bandPlot x=dynTime limitLower=dynLL1 limitUpper=dynLU1 / name="f1" &dispFillAttrs ;
        bandPlot x=dynTime limitLower=dynLL2 limitUpper=dynLU2 / name="f2" &dispFillAttrs ;
        bandPlot x=dynTime limitLower=dynLL3 limitUpper=dynLU3 / name="f3" &dispFillAttrs ;
        bandPlot x=dynTime limitLower=dynLL4 limitUpper=dynLU4 / name="f4" &dispFillAttrs ;
        bandPlot x=dynTime limitLower=dynLL5 limitUpper=dynLU5 / name="f5" &dispFillAttrs ;
        bandPlot x=dynTime limitLower=dynLL6 limitUpper=dynLU6 / name="f6" &dispFillAttrs ;

%let seriesVizAttrs = lineAttrs=(pattern=solid color=grey thickness=2px);
        seriesPlot x=dynTime y=dynLL1 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLL2 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLL3 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLL4 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLL5 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLL6 / &seriesVizAttrs ;
        seriesPlot x=dynTime y=dynLU6 / &seriesVizAttrs ;

        scatterPlot x=dynTime y=ly /
          markerCharacter=label  markerAttrs=(color=black);

      endlayout;
      entryfootnote halign=left dynFootNote /* / textattrs=graphValueText(size=7)*/; 
    endgraph;                                                               
  end;                                                                       
run;

ods _all_ close;
ods listing gpath=&gpath image_dpi=&dpi style=listing;
ods graphics / reset imagename="ThemeRiver" width=6.93in height=3.15in;

proc sgrender template=river data=sines_river_mindev;
dynamic dynTime="time"
        dynLL1="b1L" dynLU1="b1U" 
        dynLL2="b2L" dynLU2="b2U"
        dynLL3="b3L" dynLU3="b3U"
        dynLL4="b4L" dynLU4="b4U"
        dynLL5="b5L" dynLU5="b5U"
        dynLL6="b6L" dynLU6="b6U"
        dynTitle="Theme River: Variation of Pollutants over Time"
        dynFootNote="(Simulated data)  Stacked Graphs. Byron & Wattenberg. IEEE InfoVis 2008"
        ;
run;
/* Stacked Graphs. Byron L., Wattenberg M. IEEE InfoVis 2008*/
ods _all_ close;