BookmarkSubscribeRSS Feed
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10





After seeing Sanjay Matange's blog post on the use of a text plot to create a clock face, thought I'd take a shot at creating time-and-temperature clock faces from temperature forecast XML data obtained from (cold week ahead in Chicago!). OK, it's no threat to the cool Apple Watch Weather app, but it does have a literal "heat map" going for it. Smiley Happy


Btw, presenting temperature data "radially" was the subject of a recent Microsoft Research study. And way back in 2012, Sanjay Matange and Robert Alison respectively presented their SAS ODS Graphics and SAS/GRAPH takes on Ken Kleinman's interesting R-based approach.



*==> Fun w/SAS ODS Graphics: Time and Temperature "Watch Faces";

*==> Grab 7 days of forecasted hourly temperatures from XML (Chicago);

filename TimeTemp url '';
filename map '/folders/myfolders/';         * XML map to grab times/temps;
libname TimeTemp xmlv2 xmlmap=map;

data timetemp;                                          * Create dataset with 5 days of hourly temperatures;
set timetemp.times;                                     * Merge time and temperature data;
set timetemp.temps(where=(type='hourly'));              * Just hourly temps;
hr=hour(time);                                          * Hour (0-23);
if hour(time)< 12 then AmPm='AM'; else AmPm='PM';       * AM or PM?;
hr12=mod(hr,12);                                        * Change 0-23 to 0-11;
day=put(datepart(time),downame3.);                      * Grab day of week;
if '12nov2018'd<=datepart(time)<='16nov2018'd;          * Select 5 complete days;

*==> Calc x/y points for "watch faces";

data watch;                                              
array hrs[12] _TEMPORARY_ (3 2 1 0 11 10 9 8 7 6 5 4);  * Map 30-degree wedges to hour of day; 
do w=0 to 11;                                           * Create 12 polygons for wedges;
  hr12=hrs[w+1];                                        * Find hour for 30 degree wedge;
  seq=0;                                                * Polygon ID;
  x=0; y=0; output;                                     * Polygons start at 0,0;
  do a=2*constant("pi")/12*(w-.5) to 2*constant("pi")/12*(w+.5) by 0.01;    
    seq+1;                                              * Polygon sequence number;
    x=cos(a);                                           * Assume circle is radius=1;      
  xd=x; yd=y;                                           * 0,0 to xd,yd are "divider line" points for wedges;
  x=.; y=.;
  xd=.; yd=.;
  a=2*constant("pi")/12*w;                              * xt, yt are points for temperature values;
  xt=1.125*cos(a);                                      * Place temperatures outside of unit circle (radius=1);
  xt=.; yt=.;

proc sql;                                               * Merge temperature and "watch face" data;
create table tempswatch as 
select w.*, put(t.temp,3.) as txt,, t.temp, t.time, t.ampm
from timetemp t join watch w on t.hr12=w.hr12
order by datepart(t.time), w, seq;

ods _all_ close;
ods listing gpath='/folders/myfolders' image_dpi=300;
ods graphics / reset imagename='TimeTemp' height=15in width=6in noborder antialias imagefmt=png;
                                                        * Create chart - AM/PM panels for each day;
proc sgpanel data=tempswatch noautolegend aspect=1 subpixel;
panelby ampm day / onepanel uniscale=all columns=2 layout=lattice noheader noborder sort=data;
* Display day of week, AM/PM indicator in upper left corner;
inset Day ampm / nolabel position=topleft textattrs=(color=black weight=bold);
* Polygon plot hourly wedges - fill colors vary with temperature;
polygon x=x y=y id=w / fill nooutline colorresponse=temp colormodel=(lightblue darkblue);
* Vector plot divider lines;
vector x=xd y=yd / lineattrs=(color=white thickness=1.5 pattern=solid) noarrowheads;
* Text plot temperature values;
text x=xt y=yt text=txt /                
     position=center textattrs=(color=black weight=bold) strip;
colaxis display=none min=1.2 max=1.2;                   
rowaxis display=none min=1.2 max=1.2;



<?xml version="1.0" encoding="UTF-8"?>
<SXLEMAP version="1.2" name="SXLEMap">
<!-- Create TIME/TEMP SAS Datasets From XML -->

<TABLE name="TIMES">
<COLUMN name="TIME">
 <FORMAT width="19">E8601DT</FORMAT> 
 <INFORMAT width="19">B8601DT</INFORMAT>

<TABLE name="TEMPS">
<COLUMN name="TYPE" retain="YES">
<COLUMN name="TEMP">
Meteorite | Level 14

Nice work, Tc. 


Perfect segue to new SGPIE procedure (SAS 9.4M6)  that could likely help do this graph.


Also, we are working on new GTL container called LAYOUT OVERLAYPOLAR, that will support (R, Theta) coordinates with multiple plot types.  Here is an early example of a HeatMapParm.  The Radial axis is intentionally displayed at an angle. 




Yes, this post motivated by Elon Musk's Twitter posts.  🙂

Meteorite | Level 14

Happy to see use of INSETs instead of Row and Column headers.  🙂

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 2 replies
  • 2 in conversation