Click here to see the SAS code used to read in the storm data.
Click here to see the SAS code used to draw the map.
Click here to see the example. (all years)
Click here to see the example. (2010)
Click here to see the example. (2000)
Click here to see the example. (1990)
Click here to see the example. (1980)
Click here to see the example. (1970)
Note that this example is included in the book SAS/Graph: Beyond the Basics,
and all the 'tricks' used to create it are described in great detail!
My "inspiration" for this example was the following map:
First I had to find the hurricane path data.
I want to the following website, and clicked on the "Best Track" link for each region,
and then used the "Download Hurricane Database" link at the bottom of each region's page:
These text files store the data in a bit of a tricky (efficient) format.
For each storm, there is a 1-line header that tells the storm name, and year it started.
Then a line for each day of the storm, with 4 lat/long/intensity readings on each line
(one for each time 0, 6am, noon, 6pm).
Where there is no data for a certain time, some files have 0's and some have "missings".
Also, in the southern hemisphere's hurricane numbers are unique to a yearly "season",
but the seasons can cross a technical year boundary (therefore you could have 2 hurricane
#4's in the 2000 year). This makes it a bit tricky to handle later, when knowing which
obns to connect with a line, and which not to. (In hindsight, I should have probably
made use of the unique hurricane numbers, but I chose to stick with the yearly/seasonal
numbers because I could relate to them easier.)
One other "neat" thing I do is that I use a "filename url" to read the data directly
from the website, without having to save a copy to disk.
Now for the map ...
We (SAS) don't have a world map with the prime meridian on the right-hand-side
(and Europe/Asia on the left), but that's the layout that lends itself best to
plotting this storm data ... otherwise you'd have to handle storms going out
one side of the map, and coming in the other side.
I start with maps.world, and rename long & lat to x & y (I need to work with
unprojected values to do what I'm doing).
I use "proc gproject" with "project=none" to chop the map in two (and close the
resulting polygons), so that I have a left & right side.
I then add an offset to the x (longitude) values of the right side of the map,
so they wrap-around and are on the left side).
And I then put the 2 halves together into 1 data set again.
(later, I apply this same offset to the storm data in that 1/2 of the map)
I find the maximum windspeed for each storm, and sort all the storms so that
the storms with maximum windspeed with show up "on top" (ie, the red storms will
be more easily visible).
I combine the storms & the map, and "proc gproject" them using the cylindri projection.
I have to use "norangecheck" because otherwise it would think the coordinates were
out of range, because of the offset I used to put the right 1/2 on the left.
I separate the projected map and the storm data.
I then create an annotate data set with the storm data...
For each storm, on the 1st obsn I do a "move" to that location,
and then for subsequent obsns I do a "draw" (assigning the color based on
the wind speed).
When you annotate all the storms on top of the map, you can no longer see the
shorelines of the land, which can be an important "landmark" for you to be
able to see. Therefore, I create an annotate "outline" data set to annotate
on top of the colored storm paths, so I can see the land borders.
This is a *really* nice touch, imho :)
Since we're using annotate for the "response" data (storm colors), there is no
automatic color legend, therefore I create a legend by hand in the footnote text.
I use the SAS/Graph "marker" font's 'U' character to print a box, and I used
the same macro variables to control the colors (that I used in the annotate).
That's basically it!
Back to Samples Index