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.
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.
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.
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.
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.
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:
data new; set sashelp.class; proc sort; by height;run;
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.
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.
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.
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.
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.
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.
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.
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.
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;
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.