WARNING: No bars were drawn. This could have been caused by ORDER= on the AXIS statement. You might wish to use the MIDPOINTS= option on the VBAR statement instead.

What you see above is a an error issued by a SAS program like what a colleague at work recently found. The following code will reproduce this so let us walk through the steps to explain a possible cause for this.

The first stage is to create a test dataset containing variables y and x, for the vertical and midpoint axes, respectively, and populating these using a CARDS statement in a data step:

data a;
input y x;
cards;
1 5
3 9
;
run;

Now, we define an axis with tick marks for particular values that will be used as the definition for the midpoint or horizontal axis of the chart:

axis1 order=(1 3);

Then, we try creating the chart using the GCHART procedure that comes with SAS/GRAPH and this is what results in the error message being issued in the program log:

proc gchart data=a;
vbar x / freq=y maxis=axis1;
run;
quit;

The cause is that the midpoint axis tick marks are no included in the data so changing these to the actual values of the x variable removes the message and allows the creation of the required chart. Thus, the AXIS1 statement needs to become the following:

axis1 order=(5 9);

Another solution is to remove the MAXIS option from the VBAR statement and let GCHART be data driven. However, if requirements do not allow this, create a shell dataset with all expected values for the midpoint axis with y set 0 since that is used for presenting frequencies as per the FREQ option in the VBAR statement.

A first look at SAS University Edition

My first introduction to SAS came near the start of my post-university career over a decade ago. It was six weeks of classroom training and hands-on case studies that got me going with SAS 6.12. The included SAS products naturally included the components of Base SAS for data processing (data step, PROC SQL) and reporting as well as SAS/Graph. All of that was enough for a placement with one of my then employer’s clients with the added advantage of becoming one of the client’s own employees at the end of it. During that stay, more SAS versions followed until the launch of 9.1.3. Eventually, I moved onto pastures new and I remain a SAS user with 9.3 being the most recent version that I have met at work while SAS University Edition is bringing me towards 9.4.

SAS Learning Edition

Though it is possible to extend one’s knowledge on the job, that can be harder to manage during the working day when times are busy. Before SAS University Edition, we had SAS Learning Edition and I took delivery of a copy while it was available. It included SAS Enterprise Guide 4.1 together with a limited version of SAS 9 that a few limitations. Firstly it only would process up to 1500 records in any dataset but that was not such a problem for learning. Support from SAS was limited too even if the package had a price that I seem to remember was around £100 but my memory is hazy about this. What you need to remember is that SAS licenses are vastly more expensive than this so you got that for which you have paid. If you did have a Base SAS installation, Learning Edition would co-exist with it and versions like 8.2 and 9.1.3 Service Pack 4 were compatible so long as you had them pre-installed. There was a warning that re-installation of software might be required if either SAS Learning Edition or Base SAS is removed inappropriately.

Speaking of licenses, Learning Edition was time limited with its own version 2.0 (based on Enterprise Guide 2.0 and, if I recall correctly, SAS 8.2) and version 4.1 purchased prior to September 10, 2007 expiring on December 31, 2008. The expiry date for version 4.1 after the aforementioned purchase deadline was December 31, 2011. More conventionally, it was for single PC installation only and that PC had to run either Windows 2000 or Windows XP Professional. The process was one that would be more than familiar to anyone who ever installed software on a machine running Windows. Even with those older operating systems, it needed 1,080 MB of hard disk space. It reminds me of a time when 10 GB of hard drive capacity was generous but that had moved beyond 160 GB around ten years ago. The RAM requirements also fitted the time with 256 MB being the bare minimum and 512 MB being recommended.

Usefully, the whole package came with a copy of The Little SAS Book and, not having it next to me while writing these words, I cannot recall whether whether it was the version for Enterprise Guide or the Primer edition. Though I may not have made as much use of the software as I could have done, it certainly came in useful for trying a few things and I found a way to start up the more traditional SAS DMS interface as well as Enterprise Guide.

SAS University Edition

Apart for being made available free of charge, SAS University Edition is very different from its predecessor, SAS Learning Edition. After all, things have moved along since the last decade and SAS has its SAS Analytics U (for University, I presume) community now and that may explain the name though there is a wider focus on established university teaching too. Even long term SAS users like me can be called learners too so we get allowed in as well.

Firstly, it works in a very different way since you no longer are installing SAS software like you would with Microsoft Office or Adobe Photoshop. To work, it needs you to have one of Oracle VirtualBox (4.3.12 is preferred at the time of writing), VMware Player or VMware Fusion because what you are getting is a virtual machine. For those unfamiliar with such things, SAS has Quick Start guides for each:

VirtualBox

VMware Player

VMware Fusion

The available VM’s are built around Linux in that 64-bit Red Hat Enterprise Linux is installed in there with SAS running as a service on top of it. In fact, the virtual runs solely as a server with just a screen informing you of the IP address that you need to load in your web browser of choice. That reveals another break with the past with SAS Studio being used in place of Enterprise Guide or the SAS DMS. While all the processing happens within the virtual machine, it is possible to store files on your own host operating system’s file system using by setting up a shared folder called myfolders that points to where you want it and that SAS Studio can use.

The use of virtualisation to roll out a local SAS server that makes SAS Studio available is neat and means that you do not need to run Microsoft Windows on a PC as was the case with SAS Learning Edition. Mac OS X and Linux are possibilities and I use the latter at home so this is a very good thing. Furthermore, there are installation guide for each supported operating system:

Linux

OS X

OS X

The version of SAS that you get is 9.4 and it is licensed until the middle of June 2015 with a 45 day grace period taking you as far as the end of July. Along with Base SAS, you also get SAS/STAT, SAS/IML, SAS/Secure 168-bit, SAS/ACCESS Interface to PC Files, SAS/ACCESS Interface to ODBC, SAS/IML Studio, SAS Workspace Server for Local Access, SAS Workspace Server for Enterprise Access and High Performance Suite. SAS/Graph is absent but new statistical graphics procedures like SGPLOT and SGPANEL are there so graph creation possibilities should be covered anyway.

All in all, SAS University Edition looks a snazzy arrangement and I plan to explore what is offered. SAS Studio is a new to me but there are enough recognisable features to help me settle in with it and it would merit an entry of its own on here. In fact, SAS has some video tutorials on their YouTube channel that show off some of its capabilities and the new tool certainly carries over from both Enterprise Guide and the more traditional DMS interface.

Speaking of blogging, SAS has an entry on one of the theirs that it has called Free SAS Software for students!, which is another introduction to SAS University Edition. Other (non-blog) articles include Get Started With SAS® University Edition along with a useful FAQ.

Changing the working directory in a SAS session

It appears that PROC SGPLOT and other statistical graphics procedures create image files even if you are creating RTF or PDF files. By default, these are PNG files but there are other possibilities. When working with PC SAS , I have seen them written to the current working directory and that could clutter up your folder structure, especially if they are unwanted.

Being unable to track down a setting that controls this behaviour, I resolved to find a way around it by sending the files to the SAS work directory so they are removed when a SAS session is ended. One option is to set the session’s working directory to be the SAS work one and that can be done in SAS code without needing to use the user interface. As a result, you get some automation.

The method is implicit though in that you need to use an X statement to tell the operating system to change folder for you. Here is the line of code that I have used:

x “cd %sysfunc(pathname(work))”;

The X statement passes commands to an operating system’s command line and they are enclosed in quotes. %sysfunc then is a macro command that allows certain data step functions or call routines as well as some SCL functions to be executed. An example of the latter is pathname and this resolves library or file references and it is interrogating the location of the SAS work library here so it can be passed to the operating systems cd (change directory) command for processing. This method works on Windows and UNIX so Linux should be covered too, offering a certain amount of automation since you don’t have to specify the location of the SAS work library in every session due to the folder name changing all the while.

Of course, if someone were to tell me of another way to declare the location of the generated PNG files that works with RTF and PDF ODS destinations, then I would be all ears. Even direct output without image file creation would be even better. Until then though, the above will do nicely.

Some SAS Macro code for detecting the presence or absence of a variable in a dataset

Recently, I needed to put in place some code to detect the presence or absence of a variable in a dataset and I chose SAS Macro programming as the way to do what I wanted. The logic was based on a SAS sample that achieved the same result in a data step and some code that I had for detecting the presence or absence of a dataset. Mixing the two together gave me something like the following:

%macro testvar(ds=,var=);

%let dsid=%sysfunc(open(&ds,in));
%let varexist=%sysfunc(varnum(&dsid,&var));
%if &dsid > 0 %then %let rc=%sysfunc(close(&dsid));

%if &varexist gt 0 %then %put Info: Variable &var is in the &ds  dataset;
%else %put Info: Variable &var is not in the &ds  dataset;

%mend testvar;

%testvar(ds=dataset,var=var);

What this does is open up a dataset and look for the variable number in the dataset. In datasets, variables are numbered from left to right with 1 for the first one, 2 for the second and so on. If the variable is not in the dataset, the result is 0 so you know that it is not there. All of this is what the VARNUM SCL function within the SYSFUNC macro function does. In the example, this resolves to %sysfunc(varnum(&dsid,var)) with no quotes around the variable name like you would do in data step programming. Once you have the variable number or 0, then you can put in place some conditional logic that makes use of the information like what you see in the above simple example. Of course, that would be expanded to something more useful in real life but I hope it helps to show you the possibilities here.

Calculating geometric means using SAS

Recently, I needed to calculate geometric means after a break of a number of years and ended racking a weary brain until it was brought back to me. In order that I am not in the same situation again, I am recording it here and sharing it always is good too.

The first step is to take the natural log (to base e or the approximated irrational value of the mathematical constant, 2.718281828) of the actual values in the data. Since you cannot have a log of zero, the solution is either to exclude those values or substitute a small value that will not affect the overall result as is done in the data step below. In SAS, the log function uses the number e as its base and you need to use the log10 equivalent when base 10 logs are needed.

data temp;
set temp;
if result=0 then _result=0.000001;
else _result=result;
ln_result=log(_result);
run;

Next, the mean of the log values is determined and you can use any method of doing that so long as it gives the correct values. PROC MEANS is used here but PROC SUMMARY (identical to MEANS except it defaults to data set creation while that generates output by default; because of that, we need to use the NOPRINT option here), PROC UNIVARIATE or even the MEAN function in PROC SQL.

proc means data=temp noprint;
output out=mean mean=mean;
var ln_result;
run;

With the mean of the log values obtained, we need to take the exponential of the obtained value(s) using the EXP function. This returns values of the same magnitude as in the original data using the formula emean.

data gmean;
set mean;
gmean=exp(mean);
run;