Tag Archives: Maps

GMAP with WPS Analytics v4

In the last blog post, we wrote about the new features in WPS Analytics v4. I wanted to spend some time on one procedure that is new to this release and that is GMAP. GMAP allows you to create thematic maps (also known as chloropleth maps) to visually display your data among boundaries such as state, county and other political areas.

I became quite excited when I found out that mapping was going to be made available in this release. To accompany GMAP, WPS Analytics also includes a few complimentary procedures such as GREDUCE and GREMOVE. PROC GREDUCE allows you to create a lower resolution map and PROC GREMOVE provides a way for you to combine areas into larger regions.

One procedure that is missing at the moment is PROC GPROJECT. In the map below of U.S. Census Regions, you can see the output using unprojected coordinates. It may be possible to use PROC Python to project a map coordinate file to something like an Albers projection. Python has a lot of mapping routines and I wouldn’t be surprised if some developer(s) have created software to change projections.



Here is the relatively simple code for creating the map above.

data states48;
set wpsmaps.usstates50;

     if (state > ’56’) or
        (state in ( ’02’, ’15’,’07’, ’14’, ’43’, ’52’)) then delete ;

data regions;
set wpsmaps.censusregions;

if state = ’15’ or state=’02’ then delete;
label regiontext = ‘Region’;
if region=1 then regiontext=‘East   ‘;
if region=2 then regiontext=‘South  ‘;
if region=3 then regiontext=‘Midwest’;
if region=4 then regiontext=‘West   ‘;

pattern1 v=ms c=lightBlue; pattern2 v=ms c=Red;
pattern3 v=ms c=Yellow; pattern4 v=ms c=orange;

proc gmap data = regions map=states48;
  id state ;
  choro regiontext / discrete;
Title HEIGHT= .25in ‘U.S. Census Regions’;

You can also create maps at the county level. Below is another simple map that highlights the counties that are in the State of Ohio and make up the Cleveland, Columbus or Cincinnati metropolitan areas. The counties that are not part of these three MSA’s is shaded light gray.


The code that I used to create the Ohio Counties map is below.

  data oh;

  set wpsmaps.uscounties;

  where state=’39’;


  MSA=‘Other     ;

  if geoid in(‘39041’,‘39045’,‘39049’,‘39089’,‘39097’,‘39117’,‘39129’,‘39159’)

then MSA=‘Columbus  ;

if geoid in(‘39015’,‘39017’,‘39025’,‘39061’,‘39165’)

then MSA=‘Cincinnati’;

  if geoid in(‘39035’,‘39055’,‘39085’,‘39093’,‘39103’)

then MSA=‘Cleveland ‘;

  keep state county msa geoid segment;



  data ohcnty;

    set wpsmaps.uscounties;

    where state=’39’;



  *–> Create the map for the state of Ohio and define the three major MSAs;

pattern4 v=ms c=lightgray;

pattern2 v=ms c=Red;

pattern3 v=ms c=lightblue;

pattern1 v=ms c=yellow;



proc gmap data = oh(where=(segment < 5)) map=ohcnty;

 where state = ’39’;

  id state county ;

  choro msa / discrete;

Title1 HEIGHT= .25in “Ohio Counties Part of the State’s Largest MSA’s”;

 Title2 “Cleveland, Columbus, Cincinnati MSA”;

 Footnote1 HEIGHT=16pt BOLD J=Center font=Arial ” “;

 footnote2 ” “; Footnote3 ” “;

 Footnote4 HEIGHT=10pt J=left ‘Created by MineQuest Business Analytics’ J=Right font=Arial ‘PROC GMAP using WPS Analytics v4.0’;

 Footnote5 HEIGHT=10pt J=left ‘Authorized Reseller of WPS’ J=Right font=Arial “March 28, 2018 “;



With PROC GMAP and congressional district mapping data sets, you can even plot the congressional districts in a state depicting which districts are controlled by the Republicans and which are controlled by the Democrats.

Below is another WPS Analytics generated map that shows which of the nine congressional districts are held by each party.


As shipped, WPS Analytics v4.0 only contains map files for France. MineQuest has created a set of map files for the U.S. State and County outlines. These data sets were used in the creation of the two maps in this blog post.

If you licensed your WPS software from MineQuest, World Programming or other resellers, send us an email at info@minequest.com and request the map coordinate files used above. We ask that you provide contact information (Name, Company, Title, Address and Email) so we can send you brochures and updates about our services and products.

Finally, it’s worth pointing out what a great value WPS Analytics is compared to our competition. WPS continues to be added on to, fleshed out, enhanced, or whatever description you want to throw out. The product is an amazing offering with so many procedures and database engines included in the annual license fee.

Speaking of license fees, WPS Analytics is about 10% the cost of our competitors first year fees and about one-third the cost of their renewal price.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in beautiful Tucson, Arizona. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS consulting and contract programming services and is an authorized reseller of WPS in North America.

Another Update on my Ubuntu Experiment

Environments are important. Whether it’s having the right desk and office chair, the perfect office or where you chose to live, my emotional satisfaction and motivations are impacted by my environment. It doesn’t matter whether you work solo or in a small group, your environment affects how you work and how well you work. I clearly remember driving to work on I270 in Columbus, bumper-to-bumper traffic and arriving at work in such a foul mood because of the commute. I moved to Grand Rapids, MI and there experienced cold overcast skies and lots of snow. I learned that I was suffering from SAD (Seasonal Affective Disorder.) I was able to change that for myself years ago, but the same principles apply whether you are looking at your work-flow and perhaps your workstation environment as it pertains productivity and satisfaction.


Lessons learned, my commute today… Home office to patio and a lot less stress.

Another month has passed since I went over to Ubuntu as my primary OS as wanted to get back to those who may be wondering how it has gone. I must say, even with a five year-old mediocre laptop, it has gone better than I thought it would. Almost every wound I have suffered has been self inflicted.

Am I as efficient and effective as with my Windows machine? The answer is “yes.” Programming in WPS and surfing the internet has been the same experience as with my Windows machines. I have gone back to my Windows PC for bookkeeping chores when I needed. I chose not to try to move that application for this experiment. I considered it too much work and out-of-scope.

Since I started this experiment, Canonical has decided that they are going to drop their GUI interface called Unity and return to Gnome. Unity it seems, was a project that was designed to “unify” the Ubuntu experience across platforms such as tablets, phones, laptops and workstations. From my reading, the decision was made to stop the financial hemorrhaging and focus on workstations and servers at the expense of phones and tablets. I actually found Unity easy to use and not a hindrance at all.

I can understand and appreciate the reasons for that decision however. Mark Shuttleworth (founder and CEO) wrote a blog post on how and why he came to that decision. Basically, Canonical is a business (not a charitable organization) and he is treating it as such. Move to your strengths and develop those areas where the revenue stream is best.

But back to my Ubuntu experiment. I could go through each application that I use and talk about the anomalies that I discovered but that would be really boring. But suffice to say, that using LibreOffice was decent and a good enough replacement for MS Word. LibreOffice Calc was good enough for my spreadsheet needs as well. I did suffer using MS OneNote a bit. I’m a huge advocate of using OneNote to keep my ideas, plans and outlines in one place. It’s one of my go-to applications.

The issue I have with OneNote is using the online version. Unexplainably, it would insert extra space between words or even letters at random. It wouldn’t do it often, but often enough to be irritating. Perhaps it is the browser I used and I should try OneNote with a different browser.

I’ve been writing a vertical market application over the last four to six months in my free time. This is a street mapping application using R, Google Maps and WPS. WPS has worked like a champ on Ubuntu Linux. Everything I threw at it worked straight away. The Eclipse workbench is exactly the same as you would see when on Windows. As a matter of fact, I like the font used by Eclipse better than the one on Windows.


By the way, the screen shot you see above that has the WPS Workbench displayed – this is the exact same interface you see and use with WPS Link on Linux. WPS Link is the “thin client” that World Programming distributes with their server software which allows users to interactively access the WPS software as if it was running on their desktop.

So, the question to be answered is “Can I move away from using Windows as my only OS platform for everyday use?” The answer to that is “yes.” I will most likely purchase a Dell Laptop that has Ubuntu pre-installed this summer and use that as my primary development workstation. I will keep a Windows workstation so I can test and develop on that platform as well. However, now that Skype is running decently on Ubuntu, there is no reason that I can find to not use Ubuntu. What do I give up other than forced reboots and forced updates? Not much…

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in beautiful Tucson, Arizona. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS consulting and contract programming services and is an authorized reseller of WPS in North America.

Plotting Points on a Street Level Map using the Bridge to R and WPS

In the last few installments of this blog, I have shown how you can use WPS and the Bridge to R to calculate drive distances, geocode records and pull down a map from Google maps. I want to use this post to pull all this together and show how you can geocode your addresses and plot them on a street level map.

First some background you need to know about using Google for geocoding and mapping. There are limits to what Google will allow you to do with their services before they want you to start paying. You can geocode 2,500 records a day for free. You can pull down 25,000 maps a day for free. Once you start moving past these limits, there are fees involved.

One thing that you should probably start to consider is caching records locally that have been geocoded so that you don’t have to go back to the Google geocoder every time you want to plot some points on a map. I could easily run through 2,500 addresses in a day. The limitations on the number of maps is just not an issue for me. I think 25,000 maps a day is a very liberal offering for the kind of work that I would want to use the service for.

In the sample code below, I split the mapping process into two components for ease in understanding the entire process. I first geocode the file to get the latitude and longitude for each record. The second part of the process is creating a map and using the lat’s and long’s to plot points on the map. We could have put this into a single step but it wouldn’t be as clear or as flexible.

Without further ado, here’s the code using the Bridge to R and WPS.

data gasstations;
input company $1-29 address $30-52 city $53-64 state $66-67;
addr2geocode=trim(address)||', '||trim(city)||', '||trim(state);
Citgo Gas Station            5189 28th St Se        Grand Rapids MI
28th Street BP               5155 28th St Se        Grand Rapids MI
Twenty-Eighth Street C Store 5556 28th St Se        Grand Rapids MI
Speedway                     4045 28th St Se        Grand Rapids MI
Speedway                     2305 E Paris Ave Se    Grand Rapids MI
Superamerica                 2305 E Paris Ave Se    Grand Rapids MI
Shell Food Mart              3960 28th St Se        Grand Rapids MI
Admiral Petroleum            3927 28th St Se        Grand Rapids MI
Cascade C Store              4591 Cascade Rd Se     Grand Rapids MI
Friendly Food Shops          6799 Cascade Rd Se     Grand Rapids MI
Family Fare Quick Stop       6799 Cascade Rd Se     Grand Rapids MI
Cascade Citgo                6820 Cascade Rd Se     Grand Rapids MI
Dutton Fuel Mart LLC         2560 E Beltline Ave Se Grand Rapids MI
Centerpointe Marathon        2560 E Beltline Ave Se Grand Rapids MI
Shell Food Mart              2600 E Beltline Ave Se Grand Rapids MI
Speedway                     4018 Cascade Rd Se     Grand Rapids MI
Grand Rapids Gas Incorporated3214 28th St Se        Grand Rapids MI
Cascade Shell                4033 Cascade Rd Se     Grand Rapids MI
Speedway                     4665 44th St Se        Kentwood     MI
Super Petroleum Incorporated 2411 28th St Se        Grand Rapids MI

*--> Geocode the addresses using the Google Geocoder. Keep the geocoded records
     in the output dataset names locs for further processing.;


## options(repos=structure(c(CRAN="http://cran.case.edu/")))
## install.packages("ggmap", dependencies = FALSE)



   gaddress <- as.character(gasstations$addr2geocode)
   locs <- geocode(gaddress,output="more")


*--> Pull a Google map that is centered on a particular address and plot the locations
     on the map. Use the data set that was created (locs) above that contains the 
     lat and longs to plot the points.;
Title 'Gas Stations on or Near 28th Street';
Title2 'Grand Rapids, Michigan';     

addr <- locs;


map.center <- geocode('3960 28th St Se, Grand Rapids, MI');

 grmap <- qmap(c(lon=map.center$lon, lat=map.center$lat), zoom = 13,color = 'color', legend = 'topleft')
          grmap +geom_point(aes(x = lon, y = lat, size=3.0), data = addr)


The map that is created looks like this:


I cropped this down a bit and got rid of the borders so that it would be easier to view on this blog. Note the black points on the map that indicate the locations of the gas stations. We could continue this exercise by plotting a label to the points with the names of the service stations but that would be a good exercise for the reader who wants to learn more about using ggmap and street level mapping.

If you want to learn more about ggmap and street level mapping, I encourage you to take a look at the following document, “ggmap: Spatial Visualization with ggplot2 – the R Journal” and can be viewed in PDF format here. What I have presented is really a quick and dirty set of examples that just begin to scratch the surface of what ggmap can do for you.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Creating a Street Level Map with WPS and the Bridge to R

Creating a street level map using the Bridge to R and WPS is actually pretty easy. As in our other examples (see the two previous blogs) we again use ggmap to pull down a map from Google Maps and display it using HTML. Amazingly, this only takes four lines of R code. Here’s an example:




   bp <- "4045 28th St Se, Grand Rapids, MI, USA"
   qmap(bp, zoom=12)


The code is fairly easy to follow. We load the ggmap library that will do most of the work for us. We center the map using the address “4045 28th St Se, Grand Rapids, MI, USA”. The next line queries the map with a specified zoom level (we are using zoom level 12). Finally, we print the map using the print function.

This is what the map looks like.



We can actually take this a bit further. Instead of using a known address, we can us a place of interest for querying and creating the map. If we replace the address in the code above with “White House, Washington DC, USA” we get a map like below.


So know we have seen how easy it is to pull down a map from Google using ggmap and the Bridge to R for WPS. If you have a copy of the Bridge to R, I recommend you play with the demonstration programs to get an idea of what you can do with the software and the mapping service. It’s always fun to see what gets rendered using ggmap, R and the Bridge to R.

About the author: Phil Rack is President of MineQuest Business Analytics, LLC located in Grand Rapids, Michigan. Phil has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and is a authorized reseller of WPS in North America.

Creating Maps with WPS and the Bridge to R

A while back, I demonstrated how you can use the Bridge to R to create almost any graph or plot using WPS in combination with R. I showed how you can create the cowboy hat as well as some basic and not so basic charts and plots. One thing that I didn’t demonstrate was how you can create thematic maps (aka chloropleth maps) using the Bridge.

Today, I want to delve into that area a little bit and provide some programming samples that you can use to create these maps. First, you need to have a copy of the Bridge to R and WPS (or SAS) to run these demos. Some of the later code also uses the county2000 dataset available from the downloads section of the minequest.com website.

First a little background. Thematic mapping is a great way to show how certain attributes change or vary over given political boundaries. For example, depicting how states differ in terms of income tax assessment, or what are the most populous counties in the country. Providing a visual map for your users to understand variation across geography is always helpful in my opinion. R provides a library called “maps” that contains polygons for drawing thematic maps and a means for attaching a variable that you want to visually display demonstrating change over a given geography. I will show how you can use state and county outlines from R to do just that with the Bridge to R.

To draw a simple outline of the United States using the Bridge, it only takes three lines of R code. For example:

Program 1. Displaying U.S. State Outlines.

   1: *--> Outline of the United States - by state;

   2: %Rstart(dataformat=manual, data=, rGraphicsViewer=true);

   3: datalines4;


   5:  library(maps)  # load the boundary file

   6:  map("state", interior = TRUE, projection="polyconic", col="blue")

   7:  title('United States')  # draw the map


   9: ;;;;

  10: %Rstop(import=);

Map 1. U.S. State Outlines Map.


Click on map to view an expanded image

We can expand on the above map by adding one more line of code which will draw the county outlines inside of the state boundary outline.

Program 2: Creating State and County Outlines.


   2: *--> Outline of the United States - by state/county;

   3: %Rstart(dataformat=manual, data=, rGraphicsViewer=true);

   4: datalines4;


   6: library(maps)


   8:  map('county', boundary=TRUE,

   9:  interior=TRUE, projection="polyconic", col='lightgray', fill=TRUE, resolution=0, lty=1)

  10:  map('state', boundary=FALSE,

  11:      projection="polyconic", col='white', fill=FALSE, add=TRUE, lty=1)

  12: ;;;;

  13: %Rstop(import=);

Map 2. State County Outlines.

US_State_county_outline Click on map to view an expanded image

We can take this one step further by selecting only the geographic areas that we are interested in displaying by passing an argument to R passing just the regions we are interested in viewing. In this case, I’ve taken the liberty to pass the string containing the regions to R by using a macro variable. The Bridge to R can pass macro variables to R to help minimize typing and making mistakes.

Program 3. Selecting specific areas to map.

   1: *--> Great Lakes States by county - How to map a subset;

   2: %let geogarea = 'ohio','michigan','indiana','illinois','wisconsin';


   4: %Rstart(dataformat=manual, data=, rGraphicsViewer=true);

   5: datalines4;


   7: library(maps)

   8:  map('county',region= c(&geogarea), boundary=TRUE,

   9:  interior=TRUE, projection="polyconic", col='lightgray', fill=TRUE, resolution=0, lty=1)

  10:  map('state',region= c(&geogarea), boundary=FALSE,

  11:      projection="polyconic", col='white', fill=FALSE, add=TRUE, lty=1)


  13:  title('Great Lakes States')


  15: ;;;;

  16: %Rstop(import=);

When we run the code above (Program 3), we are presented with a map that just contains the counties for the Great Lakes States Ohio, Michigan, Indiana, Illinois, and Wisconsin.

Map 3. Great Lakes States.

greatlakes_states_county_outlineClick on map to view an expanded image

So far, I’ve shown you how to (1) create a map, (2) overlay two geographic areas (state and county) on a map, and (3) how to select a specific subset of the data to display (Great Lakes States) in creating your maps. Let’s move on and see how you can map your data using the Bridge to R and the R maps library.

The data I’m using to create the county population density map below is from a zip file that you can download from the MineQuest website. Basically, I’m using WPS to manipulate the data to get it into a format that R can use and then using the Bridge to R, call the mapping routines to display this data.

Program 4. Displaying your data in a thematic map.

   1: libname cntydata 'c:\data';


   3: proc format;

   4: value popval

   5: 0-24999 = 1

   6: 25000-99999=2

   7: 100000-249999=3

   8: 250000-499999=4

   9: 500000-749999=5

  10: 750000-high=6;

  11: run;



  14: data cntydata(keep=names cntypop);

  15:   set cntydata.county2000;

  16:   length names $ 32 cntypop 8;

  17:   cntypop = pop100;

  18:   if state in('02','15','72') then delete;

  19:   x=indexw(name,'County');

  20:   if x > 0 then cntyname=substr(name,1,x-1);


  22:   y=indexw(name,'Parish');

  23:   if y > 0 then cntyname=substr(name,1,y-1);


  25:   names=trim(lowcase(fipname(state)))||','||trim(lowcase(cntyname));

  26:   format cntypop popval.;

  27: run;



  30: *--> great a US map at county level showing population density;

  31: %Rstart(dataformat=csv, data=cntydata, rGraphicsViewer=true);

  32: datalines4;


  34: library(maps)  # Load the maps library

  35: popdata <- (cntydata)


  37: #define the color map to be used

  38: cols <- c("#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77", "#980043")


  40: mp <- map("county", plot=FALSE,namesonly=TRUE)

  41: # draw the county outlines

  42: map("county", col=cols[popdata[match(mp,popdata$names),]$cntypop],fill=TRUE, projection="polyconic")


  44: # Draw the state outlines

  45: map('state', boundary=FALSE,projection="polyconic", col='white', fill=FALSE, add=TRUE, lty=1)


  47: title('U.S. County Population Density')

  48: ;;;;

  49: %Rstop(import=);

Map 4. U.S. County Population Density.

us_state_county_pop_2000 Click on map to view an expanded image

Above is the map generated by the code in Program Listing 4. Personally, I think it’s a nice thematic map and does demonstrate population density by county. It obviously can be enhanced by adding a legend and perhaps a footnote, but I will leave that up to you to figure out. The code that creates the map is only seven lines long. This could easily be made into a template by users for further expanding the map as well as for code reuse purposes.

For more information on creating maps with R, visit Cran at:

http://cran.r-project.org/web/packages/maps/index.html and download the maps.pdf file.

About the author: Phil Rack is President of MineQuest, LLC. and has been a SAS language developer for more than 25 years. MineQuest provides WPS and SAS consulting and contract programming services and a reseller of WPS in North America.