1 Introduction

This document provides a basic introduction to the SAS system and the handling of data through the Data Step. No previous SAS experience is assumed. Users will need to have a licensed SAS Base product or the free SAS University version installed to run the examples. Further information may also be found through the SAS Forums and SAS Blog posts. A useful introductory text is The Little SAS Book: A Primer.

SAS is a system of data analytic tools encompassing data management, statistical analysis, graphics, reporting, and publication. SAS can be run on many different operating systems and through various user interfaces. This document will focus on running SAS in a command line framework in a Windows environment, although the basic SAS information here will translate across operating systems and interfaces. For users of Apple Mac systems, SAS can be run through either the SAS University installation mentioned above, or through a Windows SAS version installed on a virtual OS package such as Parallels Desktop (This requires a copy of Windows as well). This introduction does NOT cover SAS JMP, which is a separate point and click product for similar SAS analytical tools.

2 The SAS Windows Environment

When starting a SAS session, the user will be presented with several windows. In the default configuration, two overlapping windows on the left hand side are called Results and Explorer. In the demonstrations below, these windows are closed for better clarity and they will accessed separately as needed. The remaining windows represent the three basic components of a SAS session: An Editor, a Log window, and a Listing or Output window. The Editor is where SAS commands (programs) will be written and run. The Log window will provide a history of each program as it runs. This is useful for identifying errors, warnings, and general information about the results of the program being run. The Output window will provide a text version of any printed output from the program, such as analysis results, data printouts, etc. In more recent versions of SAS, this window has become somewhat redundant as a newer output presentation format is now available. These newer and cleaner looking outputs will automatically open up in a new window called Results Viewer when a program is run. By default, these results are produced in HTML, which can be viewed in the default SAS browser or any Web browser set by the user.

I find that reorganizing the SAS windows from their default positions and sizes is more productive. I prefer to close the Results and Explorer windows, and to make the Editor window the largest and the Log and Listing windows smaller and not overlapping. This allows me to easily see the code I am writing and watch the Log and Listing windows as needed. Each window can be accessed from the labeled tabs at the bottom of the screen.

Organized SAS windows

These changes, however, will only last the current SAS session. If we want them to reoccur every time we open SAS, we must modify the system preferences. This is done by navigating to the Tools -> Options -> Preferences drop down menu. On the Preferences window, under the General tab, check the save settings on exit box. Note that these changes will affect the Editor, Log, and Output windows, but not the Results and Explorer windows. As is evident here, there are also many other options that can be modified here as well.

Tools Menu

Preference choices

3 SAS Structure

A SAS program consists of basically two types of components: Data Steps and Procedures or PROCS. Procedures are pre-written routines for specific tasks, such as statistical analyses, graphics, importing and exporting files, etc. The Data Step is designed to handle and manipulate data. In a Data Step, we use mathematical operators, functions, logical statements, and other constructs to compute or define new variables, convert variable units, change data structures, or filter and subset a larger data set. Data Steps and PROCS are written in “Blocks” of code. Blocks begin with either of the keywords DATA or PROC and they end with a special keyword RUN. Within each Block are SAS Statements which are usually specific to a PROC or Data Step. Statements in SAS also begin with keywords and always end with a semicolon, ;. What the keywords are and how to write them is specific to each PROC or the general rules for the DATA Step. As with many written languages, statements can carry across multiple lines on the screen, or there can be multiple statements on a single line. All SAS looks for is a recognized keyword and an ending semicolon. The Blocks can contain as many statements as necessary and there can be as many DATA and PROC blocks as we need to accomplish our tasks in SAS. A SAS program then consists of one or more Blocks, written in any order required to carry out our analyses. When SAS executes a program, it starts at the top of the program, reads and carries out the instructions in the first Block. It then moves sequentially down to the next Block, etc., until it reaches the end of the program.

To run a SAS program, there are several options. The quickest is to use the run icon (a small running figure in the top menu bar). We can also use the F8 function key, or we can select submit program from the Run menu bar. Note that when running SAS code, you can use the mouse to select a portion of code before using one of these options. This will run only the selected portion of code. Make sure to select all relevant portions of the code (including semicolons), however, or SAS will only partially run the code.

3.0.0.1 Note: SAS Legacy

As an analytical software package, SAS has been around for many years. It predates the personal computer, many storage media types, and, of course, the internet. While SAS has been updated many times, some legacy terminology remains. In “The good old days”, SAS programs (and others such as Fortran) were typed into a special machine called a Card Punch. This machine physically translated the characters of the program to holes in an IBM punch card. Each card held one or more SAS statements, or at times a statement could take several cards. These were carefully aligned in order and put in a box or wrapped with a rubber band. The box was then typically carried to a central mainframe computer (“The computer center”) and the user Submitted the cards to an operator who then used a Card Reader to put the program into the computer and Run it. Users would then pick up the output Listing at a later time. Some of this legacy has been retained through subsequent software updates in the terminolgy and language syntax such as Cards, Submit, Run, and Listing.

Tools Menu

Tools Menu

Source: https://en.wikipedia.org/wiki/Punched_card


4 Programming Habits

4.1 Program Format

It is a good idea to use consistant structured formatting when writing programs (SAS or otherwise). While most computer software packages are indifferent to indentation, spacing, line breaks, etc., using these features will make your programs easier for people to read and understand. The ‘Block’ nature of SAS lends itself to this type of formating very well. Blank lines between blocks of code also improve readability and will be ignored by SAS. The code below illustrates two examples:

4.1.1 BAD

data new; set sashelp.class; proc sort; by height;run;



4.1.2 BETTER

data new;
  set sashelp.class;
run;

proc sort;
  by height;
run;



Let us ignore for a moment what exactly these codes do, but note that both sets of code will produce identical results. Remember that SAS is simply reading from keyword to semicolon, repeatedly, until it runs out of code. It does not interpret any formatting or lack of it. In the first example, all the commands are written on a single line, while the second uses line breaks, indentation, empty lines, and RUN statements to delineate Blocks. For most people, the second example is easier to read and follow. It will also be easier to interpret and debug (find & fix errors) if required. SAS makes much of this easy for the user by automatically indenting lines for you and highlighting keywords in color in its Editor. The exact type of formatting you use, however, is up to you, but you are strongly encouraged to use some type of formatting that makes your code easier to read.

4.2 Commenting and Documentation

Another important aspect of programming is documenting and commenting your code. Doing so helps others (and yourself at a future date) understand your workflow in data management and analysis. This is vital for repeatability of analyses. SAS has some abilities for this through the use of special symbols to add comment lines to a program which will tell someone reading it what the programmer had in mind when they wrote the code. The special symbols tell SAS to skip these lines since they are only for us. The format to use these is: /* comment written here */. Any text written between the /* and */ will be ignored. To accomodate longer descriptive text, the comment sections can encompass multiple lines, if needed.


/* Read in the example data Class and sort the data by height. */
  
/*
Written by Chuck Darwin
November 24, 1859
Down House, Kent, England
*/
  
data new;
  set sashelp.class;
run;

proc sort;
  by height;
run;

For more information on documenting codes and scripts, recording data workflows, and repeatability in science, see here.

5 Getting Data into SAS

When data come into SAS, they are converted into a binary SAS specific format called a SAS Data Set. Data Sets have two part names separated by a period. The first part of the name is referred to as the Library. The second name is called the Member. A Library is simply a reference to where the data is stored on the computer. By default, this is assumed to be the memory of the computer and is referred to as the Work library. If you omit the fisrt part of the name, the data will be stored in the Work library. Data stored here are only persistent during the SAS session. If you restart SAS, you will need to move the data into SAS again, in order to use it. To keep data in a SAS format, we can use a Permanent SAS Library where we define a location on the computer to store SAS data. This is done either through the menu system, or by writing a LIBNAME statement into the program. Typically, permanent SAS Data Sets are not necessary as it is easy and quick enough to read the required data in once each session. Permanent Data Sets are more common when the data in question is very large and takes a long time to read into SAS. It is also advisable to only have one source file for data, not multiple copies and formats. For these reasons we will only utilize the temporary Work library here.

The second part of the name, the Member of the library, is how you will reference the data in SAS. The name is most useful if it reflects the content of the data. For example, a member name: Finch_1835 gives us a clue that the data refers to finches collected in 1835. The full name would then be: Work.Finch_1835, although we can also leave off the Library name, i.e. Finch_1835, because Work is the default library.

The Member name could be expanded to Darwin_finch_1835_beaks_length_depth. While this is more informative, it is also more cumbersome to write out and prone to mistakes. It is best to find a medium between a short terse name and and overly long one. Best practices, however, also include documenting what the data are using comments, as outlined above, as well as good repeatable data practices such as meta files, Read.me files, etc. For more on these, please see here.

5.0.0.1 Note: SAS Naming Conventions

There are some basic rules for naming SAS Data Sets, which also apply to variables within the data sets. SAS names must be alpha-numeric characters, that is, letters and numbers. We cannot use characters such as periods, spaces, parentheses, commas, etc. The only non-standard character allowed is the underscore, ’_’. Names must also begin with a letter, not a number. Hence, Finch_1835 is allowed, but 1835_Finch is not.


5.1 Data Sources: Internal and External

Data to be read into SAS can be either Internal as part of the SAS program, or External as an independent file. While Internal data is simple to use, it will not be discussed here. Good data practices require data to be kept as a single source. Any corrections or modifications to the data should be carried out and documented through programs or scripts that start with this single data source. By incorporating data into SAS or other scripts, we create multiple copies of the data. This makes corrections and documenting the data difficult or impossible. The reader is, therefore, strongly discouraged from using Internal data.

5.2 External Data and the Data Step

The preferred means of accessing data is reading external files into SAS. SAS is extremely flexible in its ability to read various file types. Files such as text formats, common databases, and spreadssheets such as Excel are all accessible. It is even possible to define custom file formats for SAS to read, although that is beyond the scope of this tutorial. The files may consist of data that was entered manually or was created through other software or equipment, such as weather stations, data loggers, or laboratory hardware. Although there are exceptions, the files themselves are typically arranged with one observation (record) of data per line of the file. Data values (factors and variables of interest) within each line are separated or delimited by special characters. Common delimiters are spaces, tabs, and commas (Comma Separated Values; CSV). Space delimited files are the default for SAS. For this format, the data must have a rectangular structure. That is, all data positions, in all rows of the file, must have a value. This means that, if there is missing data, there must be place holder for that position in the file. SAS actually has many placeholder designations for missing data, each distinguishing between various reasons that a data point may be missing (e.g. data is out of range, subject didn’t answer question, data record is lost, etc.). The simplest form, however, is a single period in the missing data position. Note that this differs from other software like R where missing data are recorded as the characters NA. This case is covered below.

The example below illustrates a small space delimited data file for finch data having 9 lines and 4 variables per line.

5.2.1 Example: Space delimited data file

Band species Beak_length Beak_depth
2 fortis 9.4 8
9 fortis 9.2 8.3
12 fortis 9.5 7.5
15 fortis 9.5 8
305 fortis 11.5 9.9
307 fortis . 8.6
308 fortis 9.9 8.4
309 fortis 11.5 9.8
311 fortis 10.8 9.2


The first line indicates that the values in each data line are: Band (the individual ID of a tagged bird), the species of the bird, followed by its respective beak length and depth. The data then follows, with each record on a separate line and spaces inserted between values. For Band 307, a missing value has been denoted for Beak length.

This data can be read into SAS and printed using a Data Step and a procedure for displaying data, PROC PRINT:


/* Read in the example shortened version of Grant 1975 finch data. */
/* Full data at https://www.pbs.org/wgbh/evolution/library/01/6/l_016_01.html */
  
data finch_1975;
  infile '.\Data\Finch_1975_Partial.txt' firstobs=2;
  input Band Species$ length depth;
run;

proc print;
run;
Obs Band Species length depth
1 2 fortis 9.4 8.0
2 9 fortis 9.2 8.3
3 12 fortis 9.5 7.5
4 15 fortis 9.5 8.0
5 305 fortis 11.5 9.9
6 307 fortis . 8.6
7 308 fortis 9.9 8.4
8 309 fortis 11.5 9.8
9 311 fortis 10.8 9.2

SAS uses the keyword infile to designate where the external data file is located. The file location (path) is given between single quotes followed by any desired options. In this case, the option firstobs = 2 is used, forcing SAS to skip the first line of the file and start reading data on line 2. A similar option, obs = <number>, can be used in conjunction with firstobs option to read a fixed number of observations starting at the firstobs position from any portion of a file. For example, in the file above, the options firstobs = 2 Obs = 3 would cause SAS to read only the first three lines of the data, starting with line 2 and proceeding through line 4. Further options related to reading only specified columns of data, long data lines, etc, are also available and information on these may be found in the SAS help system or the relevant SAS online manuals.

The infile statement is followed by an input statement. The keyword input provides a list of the data variables in the order they will appear in the data lines of the file. The variable names in the list should follow the SAS alpha-numeric naming conventions described above. In this example, there are 4 variables. Unlike the other 3 variables, Species is a non-numeric character value. For this type of data, SAS requires a dollar sign ($) to follow the variable name. The other variables are not modified this way and will be assumed to have the default format, numeric. This input type is called List input, for obvious reasons. In most cases, List input will be sufficient, however, should you require them, other forms of the input statement such as Column or Formatted types are also available to specify exact positions in a data line or special data types such as dates, respectively.

An analogous example for a file that contains the value NA for the missing data in band 307 would be:


proc format;
invalue has_NA 'NA' = .;
run;
  
data finch_1975;
  infile '.\Data\Finch_1975_Partial.NA.txt' firstobs=2;
  informat Beak_length has_NA.;
  input Band Species$ length depth;
run;

Here the procedure Proc Format is used to define NA as missing under the label “has_NA”. In the data step, an informat statement is then used to call this definition for Beak_length.

5.2.2 Non-space Delimiters

The space delimted file is simple to set up, but it can cause issues in practice when the data values themselves contain spaces. For example, the Species name above may be recorded as G. fortis, indicating the genus Geospiza. If we use the default space delimited input above for this, SAS will try to read 5 data values per line instead of 4 and get out of alignment in the input sequence. Species will be set to G., length to the value fortis and the length value will end up under depth. While this situation can be corrected by carefully aligning data values across lines and using Formatted input, an easier solution may be to change the delimiter character to something other than a space. A common non-space delimiter is the comma. Many software and digital equipment output files use comma separated values (CSV). In order to use these files in SAS, we add a new option, delimiter, to the infile statement. The delimiter option for a comma is intuitively given as Delimiter = ‘,’. SAS can also specify multiple characters as delimiters, such as delimiter = ‘,;’ which would treat either a comma or semicolon as a separator of data values.

5.2.3 Example: Comma delimited data file and SAS code

Band species Beak_length Beak_depth
2,G. fortis,9.4,8
9,G. fortis,9.2,8.3
12,G. fortis,9.5,7.5
15,G. fortis,9.5,8
305,G. fortis,11.5,9.9
307,G. fortis,.,8.6
308,G. fortis,9.9,8.4
309,G. fortis,11.5,9.8
311,G. fortis,10.8,9.2



/* Read in the example Grant finch data. */
  
data finch_1975;
  infile '.\Data\Finch_1975_Partial.csv' firstobs=2 delimiter=',';
  input Band Species$ length depth;
run;



5.2.3.1 Note: Non-standard delimiter characters

Sometimes data files will have non-standard delimiter characters that are not visibly obvious when typed. A common example of this is a Tab. These characters must be specified in a special manner called hexadecimal, which is simply a computer code for each keyboard character, including Tabs. The hexadecimal codes can be found in most programming texts or through an online search. For a Tab, the code is 09. Thus, the correct option for reading Tab delimited files would be: delimiter = ’09’x. Here the “x” at the end tells SAS to treat the number 09 as a hexadecimal value. Note that the single quotes are required around the number portion, but not the x. Although it is not necessary, other characters could be specified as hexadecimal as well, e.g. a comma would be delimiter = ’2C’x or a semicolon, delimiter = ’3B’x where the 2C and 3B are the hexadecimal codes for comma and semicolon, respectively.


5.3 External Data and SAS Menu System

An alternative to the Data Step for reading in external files is the SAS Menu System. This system handles all the details of importing data in the background while the user uses drop down menus to select the appropriate options. To start the import process, Select the File -> Import Data menu item. This starts a windowing dialog:

Organized SAS windows

From here we can select the data source Comma Separated Values (*.csv).