5. SAS Variables and Assignment Statements

Once you’ve read your data into a SAS data set, surely you want to do something with it. A common thing to do is to change the original data in some way in an attempt to answer a research question of interest to you. You can change the data in one of two ways:

  1. You can use a basic assignment statement in which you add some information to all of the observations in the data set. Some assignment statements may take advantage of the numerous SAS functions that are available to make programming certain calculations easier (e.g., taking an average).

  2. Alternatively, you can use an if-then-else statement to add some information to some but not all of the observations. In this lesson, we will learn how to use assignment statements and numeric SAS functions to change your data, and then, we will learn how to use if-then-else statements to change a subset of your data.

Modifying your data may involve not only changing the values of a particular variable, but also the type of the variable. That is, you might need to change a character variable to a numeric variable. For that reason, we’ll investigate how to use the INPUT function to convert character data values to numeric values.

5.1. Assignment Statement Basics

The fundamental method of modifying the data in a data set is by way of a basic assignment statement. Such a statement always takes the form:

variable = expression;

where variable is any valid SAS name and expression is the calculation that is necessary to give the variable its values. The variable must always appear to the left of the equal sign and the expression must always appear to the right of the equal sign. As always, the statement must end with a semicolon (;).

Because assignment statements involve changing the values of variables, in the process of learning about assignment statements we’ll get practice with working with both numeric and character variables. We’ll also learn how using numeric SAS functions can help to simplify some of our calculations.

Example

Throughout this lesson, we'll work on modifying various aspects of the temporary data set grades that is created in the following DATA step:
DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 p1 f1;
RUN;
SAS Connection established. Subprocess id is 6555
SAS Output

The SAS System

Obs name e1 e2 e3 e4 p1 f1
1 Alexander Smith 78 82 86 69 97 80
2 John Simon 88 72 86 . 100 85
3 Patricia Jones 98 92 92 99 99 93
4 Jack Benedict 54 63 71 49 82 69
5 Rene Porter 100 62 88 74 98 92

The data set contains student names (name), each of their four exam grades (e1, e2, e3, e4), their project grade (p1), and their final exam grade (f1).

A couple of comments. For the sake of the examples that follow, we'll use the DATALINES statement to read in the data. We could have just as easily used the INFILE statement. Additionally, for the sake of ease, we'll create temporary data sets rather than permanent ones. Finally, after each SAS DATA step, we'll use the PRINT procedure to print all or part of the resulting SAS data set for your perusal.

Example

The following SAS program illustrates a very simple assignment statement in which SAS adds up the four exam scores of each student and stores the result in a new numeric variable called examtotal.

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    * add up each students four exam scores
      and store it in examtotal;
    examtotal = e1 + e2 + e3 + e4;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 examtotal;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 examtotal
1 Alexander Smith 78 82 86 69 315
2 John Simon 88 72 86 . .
3 Patricia Jones 98 92 92 99 381
4 Jack Benedict 54 63 71 49 237
5 Rene Porter 100 62 88 74 324

Note that, as previously described, the new variable name examtotal appears to the left of the equal sign, while the expression that adds up the four exam scores (e1+e2+e3+e4) appears to the right of the equal sign.

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the new numeric variable examtotal is indeed the sum of the four exam scores for each student appearing in the data set. Also note what SAS does when it is asked to calculate something when some of the data are missing. Rather than add up the three exam scores that do exist for John Simon, SAS instead assigns a missing value to his examtotal. If you think about it, that's a good thing! Otherwise, you'd have no way of knowing that his examtotal differed in some fundamental way from that of the other students. The important lesson here is to always be aware of how SAS is going to handle the missing values in your data set when you perform various calculations!

Example

In the previous example, the assignment statement created a new variable in the data set by simply using a variable name that didn't already exist in the data set. You need not always use a new variable name. Instead, you could modify the values of a variable that already exists. The following SAS program illustrates how the instructor would modify the variable e2, say for example, if she wanted to modify the grades of the second exam by adding 8 points to each student's grade:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    e2 = e2 + 8;  * add 8 to each student's
                    second exam score (e2);
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 p1 f1;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 p1 f1
1 Alexander Smith 78 90 86 69 97 80
2 John Simon 88 80 86 . 100 85
3 Patricia Jones 98 100 92 99 99 93
4 Jack Benedict 54 71 71 49 82 69
5 Rene Porter 100 70 88 74 98 92

Note again that the name of the variable being modified (e2) appears to the left of the equal sign, while the arithmetic expression that tells SAS to add 8 to the second exam score (e2+8) appears to the right of the equal sign. In general, when a variable name appears on both sides of the equal sign, the original value on the right side is used to evaluate the expression. The result of the expression is then assigned to the variable on the left side of the equal sign.

Launch and run the SAS program. Review the output from the print procedure to convince yourself that the values of the numeric variable e2 are indeed eight points higher than the values in the original data set.

5.2. Arithmetic Calculations Using Arithmetic Operators

All we’ve done so far is add variables together. Of course, we could also subtract, multiply, divide or exponentiate variables. We just have to make sure that we use the symbols that SAS recognizes. They are:

Operation Symbol Assignment Statement Action Taken
addition + a = b + c; add b and c
subtraction - a = b - c; subtract c from b
multiplication * a = b * c; multiply b and c
division / a = b / c; divide b by c
exponentiation ** a = b ** c; raise b to the power of c
negative prefix - a = -b; take the negative of b

As is the case in other programming languages, you can perform more than one operation in an assignment statement. The operations are performed as they are for any mathematical expression, namely:

  • exponentiation is performed first, then multiplication and division, and finally addition and subtraction

  • if multiple instances of addition, multiple instances of subtraction, or addition and subtraction appear together in the same expression, the operations are performed from left to right

  • if multiple instances of multiplication, multiple instances of division, or multiplication and division appear together in the same expression, the operations are performed from left to right

  • if multiple instances of exponentiation occur in the same expression, the operations are performed right to left

  • operations in parentheses are performed first

It’s that last bullet that I think is the most helpful to know. If you use parentheses to specifically tell SAS what you want calculated first, then you needn’t worry as much about the other rules. Let’s take a look at two examples.

Example

The following example contains a calculation that illustrates the standard order of operations. Suppose a statistics instructor calculates the final grade by weighting the average exam score by 0.6, the project score by 0.2, and the final exam by 0.2. The following SAS program illustrates how the instructor (incorrectly) calculates the students' final grades:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    final = 0.6*e1+e2+e3+e4/4 + 0.2*p1 + 0.2*f1;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 p1 f1 final;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 p1 f1 final
1 Alexander Smith 78 82 86 69 97 80 267.45
2 John Simon 88 72 86 . 100 85 .
3 Patricia Jones 98 92 92 99 99 93 305.95
4 Jack Benedict 54 63 71 49 82 69 208.85
5 Rene Porter 100 62 88 74 98 92 266.50

Well, okay, so the instructor should stick to statistics and not mathematics. As you can see in the assignment statement, the instructor is attempting to tell SAS to average the four exam scores by adding them up and dividing by 4, and then multiplying the result by 0.6. Let's see what SAS does instead. Launch and run the SAS program, and review the output to see if you can figure out what SAS did, say, for the first student Alexander Smith. If you're still not sure, review the rules for the order of the operations again. The rules tell us that SAS first:

  • takes Alexander's first exam score 78 and multiples it by 0.6 to get 46.8
  • takes Alexander's fourth exam score 69 and divides it by 4 to get 17.25
  • takes Alexander's project score 97 and multiplies it by 0.2 to get 19.4
  • takes Alexander's final exam score 80 and multiplies it by 0.2 to get 16.0

Then, SAS performs all of the addition:

46.8 + 82 + 86 + 17.25 + 19.4 + 16.0

to get his final score of 267.45. Now, maybe that's a final score that Alexander wants, but it is still fundamentally wrong. Let's see if we can help set the statistics instructor straight by taking advantage of that last rule that says operations in parentheses are performed first.

Example

The following example contains a calculation that illustrates the standard order of operations. Suppose a statistics instructor calculates the final grade by weighting the average exam score by 0.6, the project score by 0.2, and the final exam by 0.2. The following SAS program illustrates how the instructor (correctly) calculates the students' final grades:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    final = 0.6*((e1+e2+e3+e4)/4) + 0.2*p1 + 0.2*f1;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 p1 f1 final;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 p1 f1 final
1 Alexander Smith 78 82 86 69 97 80 82.65
2 John Simon 88 72 86 . 100 85 .
3 Patricia Jones 98 92 92 99 99 93 95.55
4 Jack Benedict 54 63 71 49 82 69 65.75
5 Rene Porter 100 62 88 74 98 92 86.60

Let's dissect the calculation of Alexander's final score again. The assignment statement for final tells SAS:

  • to first add Alexander's four exam scores (78, 82, 86, 69) to get 315
  • and then divide that total 315 by 4 to get an average exam score of 78.75
  • and then multiply the average exam score 78.75 by 0.6 to get 47.25
  • and then take Alexander's project score 97 and multiply it by 0.2 to get 19.4
  • and then take Alexander's final exam score 80 and multiply it by 0.2 to get 16.0

Then, SAS performs the addition of the last three items:

47.25 + 19.4 + 16.0

to get his final score of 82.65. There, that sounds much better. Sorry, Alexander.

Launch and run the SAS program to see how we did. Review the output from the print procedure to convince yourself that the final grades have been calculated as the instructor wishes. By the way, note again that SAS assigns a missing value to the final grade for John Simon.

In this last example, we calculated the students' average exam scores by adding up their four exam grades and dividing by 4. We could have instead taken advantage of one of the many numeric functions that are available in SAS, namely that of the MEAN function.

5.3. Numeric Functions

Just as is the case for other programming languages, such as C++ or S-Plus, a SAS function is a pre-programmed routine that returns a value computed from one or more arguments. The standard form of any SAS function is:

functionname(argument1, argument2,…);

For example, if we want to add three variables, a, b and c, using the SAS function SUM and assign the resulting value to a variable named d, the correct form of our assignment statement is:

d = sum(a, b, c) ;

In this case, sum is the name of the function, d is the target variable to which the result of the SUM function is assigned, and a, b, and c are the function’s arguments. Some functions require a specific number of arguments, whereas other functions, such as SUM, can contain any number of arguments. Some functions require no arguments. As you’ll see in the examples that follow, the arguments can be variable names, constants, or even expressions.

SAS offers arithmetic, financial, statistical and probability functions. There are far too many of these functions to explore them all in detail, but let’s take a look at some examples.

Example

In the previous example, we calculated students' average exam scores by adding up their four exam grades and dividing by 4. Alternatively, we could use the MEAN function. The following SAS program illustrates the calculation of the average exam scores in two ways — by definition and by using the MEAN function:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    * calculate the average by definition;
    avg1 = (e1+e2+e3+e4)/4;
    * calculate the average using the mean function;
    avg2 = mean(e1,e2,e3,e4);
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 avg1 avg2;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 avg1 avg2
1 Alexander Smith 78 82 86 69 78.75 78.75
2 John Simon 88 72 86 . . 82.00
3 Patricia Jones 98 92 92 99 95.25 95.25
4 Jack Benedict 54 63 71 49 59.25 59.25
5 Rene Porter 100 62 88 74 81.00 81.00

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the two methods of calculating the average exam scores do indeed yield the same results:

Oooops! What happened? SAS reports that the average exam score for John Simon is 82 when the average is calculated using the MEAN function, but reports a missing value when the average is calculated using the definition. If you study the results, you'll soon figure out that when calculating an average using the MEAN function, SAS ignores the missing values and goes ahead and calculates the average based on the available values.

We can't really make some all-conclusive statement about which method is more appropriate, as it really depends on the situation and the intent of the programmer. Instead, the (very) important lesson here is to know how missing values are handled for the various methods that are available in SAS! We can't possibly address all of the possible calculations and functions in this course. So ... you would be wise to always check your calculations out on a few representative observations to make sure that your SAS programming is doing exactly as you intended. This is another one of those good programming practices to jot down.

Although you can refer to SAS Help and Documentation (under "functions, by category") for a full accounting of the built-in numeric functions that are available in SAS, here is a list of just some of the numeric functions that can be helpful when performing statistical analyses:

Common Functions Example
INT: the integer portion of a numeric value a = int(x);
ABS: the absolute value of the argument a = abs(x);
SQRT: the square root of the argument a = sqrt(x);
MIN: the minimum value of the arguments a = min(x, y, z);
MAX: the maximum value of the arguments a = max(x, y, z);
SUM: the sum of the arguments a = sum(x, y, z);
MEAN: the mean of the arguments a = mean(x, y, z);
ROUND: round the argument to the specified unit a = round(x, 1);
LOG: the log (base e) of the argument a = log(x);
LAG: the value of the argument in the previous observation a = lag(x);
DIF: the difference between the values of the argument in the current and previous observations a = dif(x);
N: the number of non-missing values of the argument a = n(x);
NMISS: the number of missing values of the argument a = nmiss(x);

I have used the INT function a number of times when dealing with numbers whose first few digits contain some additional information that I need. For example, the area code in this part of Pennsylvania is 814. If I have phone numbers that are stored as numbers, say, as 8142341230, then I can use the INT function to extract the area code from the number. Let's take a look at an example of this use of the INT function.

Example

The following SAS program uses the INT function to extract the area codes from a set of ten-digit telephone numbers:

DATA grades;
    input name $ 1-15 phone e1 e2 e3 e4 p1 f1;
    areacode = int(phone/10000000);
    DATALINES;
Alexander Smith 8145551212  78 82 86 69  97 80
John Simon      8145562314  88 72 86  . 100 85
Patricia Jones  7175559999  98 92 92 99  99 93
Jack Benedict   5705551111  54 63 71 49  82 69
Rene Porter     8145542323 100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name phone areacode;
RUN;
SAS Output

The SAS System

Obs name phone areacode
1 Alexander Smith 8145551212 814
2 John Simon 8145562314 814
3 Patricia Jones 7175559999 717
4 Jack Benedict 5705551111 570
5 Rene Porter 8145542323 814

In short, the INT function returns the integer part of the expression contained within parentheses. So, if the phone number is 8145562314, then int(phone/10000000) becomes int(814.5562314) which becomes, as claimed, the area code 814. Now, launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that the area codes are calculated as claimed.

Example

One really cool thing is that you can nest functions in SAS (as you can in most programming languages). That is, you can compute a function within another function. When you nest functions, SAS works from the inside out. That is, SAS performs the action in the innermost function first. It uses the result of that function as the argument of the next function, and so on. You can nest any function as long as the function that is used as the argument meets the requirements for the argument.The following SAS program illustrates nested functions when it rounds the students' exam average to the nearest unit:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    *calculate the average using the mean function
     and then round it to the nearest digit;
    avg = round(mean(e1,e2,e3,e4),1);
    DATALINES;
Alexander Smith   78 82 86 69  97 80
John Simon        88 72 86  . 100 85
Patricia Jones    98 92 92 99  99 93
Jack Benedict     54 63 71 49  82 69
Rene Porter      100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 avg;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 avg
1 Alexander Smith 78 82 86 69 79
2 John Simon 88 72 86 . 82
3 Patricia Jones 98 92 92 99 95
4 Jack Benedict 54 63 71 49 59
5 Rene Porter 100 62 88 74 81

For example, the average of Alexander's four exams is 78.75 (the sum of 78, 82, 86, and 69 all divided by 4). Thus, in calculating avg for Alexander, 78.75 becomes the argument for the ROUND function. That is, 78.75 is rounded to the nearest one unit to get 79. Launch and run the SAS program, and review the output from the PRINT procedure to convince yourself that the exam averages avg are rounded as claimed.

5.4. Assigning Character Variables

So far, all of our examples have pertained to numeric variables. Now, let’s take a look at adding a new character variable to your data set or modifying an existing characteric variable in your data set. In the previous lessons, we learned how to read the values of a character variable by putting a dollar sign ($) after the variable’s name in the INPUT statement. Now, you can update a character variable (or create a new character variable!) by specifying the variable’s values in an assignment statement.

Example

When creating a new character variable in a data set, most often you will want to assign the values based on certain conditions. For example, suppose an instructor wants to create a character variable called status which indicates whether a student "passed" or "failed" based on their overall final grade. A grade below 65, say, might be considered a failing grade, while a grade of 65 or higher might be considered a passing grade. In this case, we would need to make use of an if-then-else statement. We'll learn more about this kind of statement in a later section, but you'll get the basic idea here. The following SAS program illustrates the creation of a new character variable called status using an assignment statement in conjunction with an if-then-else statement:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    * calculate the average using the mean function;
    avg = mean(e1,e2,e3,e4); 
    * if the average is less than 65 indicate failed,
      otherwise indicate passed;
    if (avg < 65) then status = 'Failed';
    else status = 'Passed';
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 avg status;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 avg status
1 Alexander Smith 78 82 86 69 78.75 Passed
2 John Simon 88 72 86 . 82.00 Passed
3 Patricia Jones 98 92 92 99 95.25 Passed
4 Jack Benedict 54 63 71 49 59.25 Failed
5 Rene Porter 100 62 88 74 81.00 Passed

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the values of the character variable status have been assigned correctly. As you can see, to specify a character variable's value using an assignment statement, you enclose the value in quotes. Some comments:

  • You can use either single quotes or double quotes. Change the single quotes in the above program to double quotes, and re-run the SAS program to convince yourself that the character values are similarly assigned.
  • You can use either single quotes or double quotes. Change the single quotes in the above program to double quotes, and re-run the SAS program to convince yourself that the character values are similarly assigned.

5.5. Converting Data

Suppose you are asked to calculate sales income using the price and the number of units sold. Pretty straightforward, eh? As long as price and units are stored in your data set as numeric variables, then you could just use the assignment statement:

sales = price * units;

It may be the case, however, that price and units are instead stored as character variables. Then, you can imagine it being a little odd trying to multiply price by units. In that case, the character variables price and units first need to be converted to numeric variables price and units. How SAS helps us do that is the subject of this section. To be specific, we’ll learn how the INPUT function converts character values to numeric values.

The reality though is that SAS is a pretty smart application. If you try to do something to a character variable that should only be done to a numeric variable, SAS automatically tries first to convert the character variable to a numeric variable for you. The problem with taking this lazy person’s approach is that it doesn’t always work the way you’d hoped. That’s why, by the end of our discussion, you’ll appreciate that the moral of the story is that it is always best for you to perform the conversions yourself using the INPUT function.

Example

The following SAS program illustrates how SAS tries to perform an automatic character-to-numeric conversion of standtest and e1, e2, e3, and e4 so that arithmetic operations can be performed on them:

DATA grades;
    input name $ 1-15 e1 $ e2 $ e3 $ e4 $ standtest $;
    avg = round(mean(e1,e2,e3,e4),1); 
    std = standtest/4;
    DATALINES;
Alexander Smith   78 82 86 69   1,210
John Simon        88 72 86  .     990
Patricia Jones    98 92 92 99   1,010
Jack Benedict     54 63 71 49     875
Rene Porter      100 62 88 74   1,180
;
RUN;

256  ods listing close;ods html5 (id=saspy_internal) file=stdout options(bitmap_mode='inline') device=svg style=HTMLBlue; ods
256! graphics on / outputfmt=png;
NOTE: Writing HTML5(SASPY_INTERNAL) Body file: STDOUT
257
258 DATA grades;
259 input name $ 1-15 e1 $ e2 $ e3 $ e4 $ standtest $;
260 avg = round(mean(e1,e2,e3,e4),1);
261 std = standtest/4;
262 DATALINES;
NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
260:22 260:25 260:28 260:31 261:11
NOTE: Invalid numeric data, standtest='1,210' , at line 261 column 11.
RULE:----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
263 Alexander Smith 78 82 86 69 1,210
name=Alexander Smith e1=78 e2=82 e3=86 e4=69 standtest=1,210 avg=79 std=. _ERROR_=1 _N_=1
NOTE: Invalid numeric data, standtest='1,010' , at line 261 column 11.
265 Patricia Jones 98 92 92 99 1,010
name=Patricia Jones e1=98 e2=92 e3=92 e4=99 standtest=1,010 avg=95 std=. _ERROR_=1 _N_=3
NOTE: Invalid numeric data, standtest='1,180' , at line 261 column 11.
267 Rene Porter 100 62 88 74 1,180
name=Rene Porter e1=100 e2=62 e3=88 e4=74 standtest=1,180 avg=81 std=. _ERROR_=1 _N_=5
NOTE: Missing values were generated as a result of performing an operation on missing values.
Each place is given by: (Number of times) at (Line):(Column).
3 at 261:20
NOTE: The data set WORK.GRADES has 5 observations and 8 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds

268 ;
269 RUN;
270
271 ods html5 (id=saspy_internal) close;ods listing;

272

Okay, first note that for some crazy reason all of the data in the data set have been read in as character data. That is, even the exam scores (e1, e2, e3, e4) and the standardized test scores (standtest) are stored as character variables. Then, when SAS goes to calculate the average exam score (avg), SAS first attempts to convert e1, e2, e3, and e4 to numeric variables. Likewise, when SAS goes to calculate a new standardized test score (std), SAS first attempts to convert standtest to a numeric variable. Let's see how it does. Launch and run the SAS program, and before looking at the output window, take a look at the log window. You should see something that looks like the log shown above:

The first NOTE that you see is a standard message that SAS prints in the log to warn you that it performed an automatic character-to-numeric conversion on your behalf. Then, you see three NOTE about invalid numeric data concerning the standtest values 1,210, 1,010, and 1,180. In case you haven't figured it out yourself, it's the commas in those numbers that is throwing SAS for a loop. In general, the automatic conversion produces a numeric missing value from any character value that does not conform to standard numeric values (containing only digits 0, 1, ..., 9, a decimal point, and plus or minus signs). That's why that fifth NOTE is there about missing values being generated. The output itself:

PROC PRINT data = grades;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 standtest avg std
1 Alexander Smith 78 82 86 69 1,210 79 .
2 John Simon 88 72 86   990 82 247.50
3 Patricia Jones 98 92 92 99 1,010 95 .
4 Jack Benedict 54 63 71 49 875 59 218.75
5 Rene Porter 100 62 88 74 1,180 81 .

shows the end result of the attempted automatic conversion. The calculation of avg went off without a hitch because e1, e2, e3, and e4 contain standard numeric values, whereas the calculation of std did not because standtest contains nonstandard numeric values. Let's take this character-to-numeric conversion into our own hands.

Example

The following SAS program illustrates the use of the INPUT function to convert the character variable standtest to a numeric variable explicitly so that an arithmetic operation can be performed on it:

DATA grades;
    input name $ 1-15 e1 $ e2 $ e3 $ e4 $ standtest $;
    std = input(standtest,comma5.)/4;
    DATALINES;
Alexander Smith   78 82 86 69   1,210
John Simon        88 72 86  .     990
Patricia Jones    98 92 92 99   1,010
Jack Benedict     54 63 71 49     875
Rene Porter      100 62 88 74   1,180
;
RUN;
 
PROC PRINT data = grades;
    var name standtest std;
RUN;
SAS Output

The SAS System

Obs name standtest std
1 Alexander Smith 1,210 302.50
2 John Simon 990 247.50
3 Patricia Jones 1,010 252.50
4 Jack Benedict 875 218.75
5 Rene Porter 1,180 295.00

The only difference between the calculation of std here and of that in the previous example is that the standtest variable has been inserted here into the INPUT function. The general form of the INPUT function is:

INPUT(source, informat)

where

  • source is the character variable, constant or expression to be converted to a numeric variable
  • informat is a numeric informat that allows you to read the values stored in source

In our case, standtest is the character variable we are trying to convert to a numeric variable. The values in standtest conform to the comma5. informat, and hence its specification in the INPUT function.

Let's see how we did. Launch and run the SAS program, and again before looking at the output window, take a look at the log window. You should see something that now looks like this:

Ahhaa! No warnings about SAS taking over our program and performing automatic conversions. That's because we are in control this time! Now, looking at the output (see above), we see that we successfully calculated std this time around. That's much better!

A couple of closing comments. First, I might use our discussion here to add another item to your growing list of good programming practices. Whenever possible, make sure that you are the one who is in control of your program. That is, know what your program is doing at all times, and if it's not doing what you'd expect it to do for all situations, then rewrite it in such a way to make sure that it does.

Second, you might be wondering "geez, we just spent all this time talking about character-to-numeric conversions, but what happens if I have to do a numeric-to-character conversion instead?" Don't worry ... SAS doesn't let you down. If you try to do something to a numeric variable that should only be done to a character variable, SAS automatically tries first to convert the character variable to a numeric variable. If that doesn't work, then you'll want to use the PUT function to convert your numeric values to character values explicitly. We'll address the PUT function in Stat 481 when we learn about character functions in depth.

5.6. If-Then Statements

In this lesson, we investigate a number of examples that illustrate how to change a subset of the observations in our data set. In SAS, the most common way to select observations that meet a certain condition is to utilize an if-then statement. The basic form of the statement is:

IF (condition is true) THEN (take this action);

In the previous lesson, we looked at an example in which the condition was:

avg < 65

and the action was:

status = ‘Failed’

For each observation, SAS evaluates the condition that follows the keyword IF — in this case, is the student’s average less than 65? — to determine if it is true or false. If the condition is true, SAS takes the action that follows the keyword THEN — in this case, change the student’s status to ‘Failed.’ If the conditon is false, SAS ignores the THEN clause and proceeds to the next statement in the DATA step. The condition always involves a comparison of some sort, and the action taken is typically some sort of assignment statement.

Example

There is nothing really new here. You've already seen an if-then(-else) statement in the previous lesson. Our focus there was primarily on the assignment statement. Here, we'll focus on the entire if-then statement, including the condition. The following SAS program creates a character variable status, whose value depends on whether or not the student's first exam grade is less than 65:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    * if the first exam is less than 65 indicate failed;
    if (e1 < 65) then status = 'Failed';
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 status;
RUN;
SAS Output

The SAS System

Obs name e1 status
1 Alexander Smith 78  
2 John Simon 88  
3 Patricia Jones 98  
4 Jack Benedict 54 Failed
5 Rene Porter 100  

First, note that we continue to work with the grades data set from the last section. Again, the data set contains student names (name), each of their four exam grades (e1, e2, e3, e4), their project grade (p1), and their final exam grade (f1). Then, launch and run the SAS program. Review the output from the print procedure to convince yourself that the values of the character variable status have been assigned correctly.

5.7. Comparison Operators

In the previous example, we used the less-than sign to make the comparison. We can use any of the standard comparison operators to make our comparisons as long as we follow the syntax that SAS expects, which is:

Comparison SAS syntax Alternative SAS syntax
less than < LT
greater than > GT
less than or equal to <= LE
greater than or equal to >= GE
equal to = EQ
not equal to ^= NE
equal to one of a list in IN

It doesn’t really matter which of the two syntax choices you use. It’s just a matter of preference. To convince yourself that you understand how to use the alternative SAS syntax though, replace the less-than sign (<) in the Example program with the letters “LT” (or “lt”). Then, re-run the SAS program and review the output from the PRINT procedure to see that the program indeed performs as expected.

Example

The following SAS program uses the IN operator to identify those students who scored a 98, 99, or 100 on their project score. That is, students whose p1 value equals either 98, 99, or 100 are assigned the value 'Excellent' for the project variable:

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    if p1 in (98, 99, 100) then project = 'Excellent';
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name p1 project;
RUN;
SAS Output

The SAS System

Obs name p1 project
1 Alexander Smith 97  
2 John Simon 100 Excellent
3 Patricia Jones 99 Excellent
4 Jack Benedict 82  
5 Rene Porter 98 Excellent

Launch and run the SAS program and review the output from the PRINT procedure to convince yourself that the program performs as described.

Note! After being introduced to the comparison operators, students are often tempted to use the syntax EQ in an assignment statement. If you try it, you'll soon learn that SAS will hiccup at you. Assignment statements must always use the equal sign (=).

5.8. Alternative Actions: ELSE statements

There may be occasions when you want to use an if-then-else statement instead of just an if-then statement. In a previous example, we told SAS only what to do if the condition following the IF keyword was true. By including an else statement, we can tell SAS what to do if the condition following the IF keyword is false.

Example

The following SAS program creates a character variable status, whose value is "Failed" IF the student's first exam grade is less than 65, otherwise (i.e., ELSE) the value is "Passed":

DATA grades;
    input name $ 1-15 e1 e2 e3 e4 p1 f1;
    * if the first exam is less than 65 indicate failed;
    if (e1 < 65) then status = 'Failed';
    * otherwise indicate passed;
    else status = 'Passed';
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 status;
RUN;
SAS Output

The SAS System

Obs name e1 status
1 Alexander Smith 78 Passed
2 John Simon 88 Passed
3 Patricia Jones 98 Passed
4 Jack Benedict 54 Failed
5 Rene Porter 100 Passed

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the values of the character variable status have been assigned correctly.

Note that, in general, using ELSE statements with IF-THEN statements can save resources:

  • Using IF-THEN statements without the ELSE statement causes SAS to evaluate all IF-THEN statements.
  • Using IF-THEN statements with the ELSE statement causes SAS to execute IF-THEN statements until it encounters the first true statement. Subsequent IF-THEN statements are not evaluated.

For greater efficiency, you should construct your IF-THEN-ELSE statements with conditions of decreasing probabilities.

5.9. Logical Operators

In addition to the comparison operators that we learned previously, we can also use the following logical operators:

Operation SAS syntax Alternative SAS syntax
are both conditions true? & AND
is either condition true? | OR
reverse the logic of a comparison ^ or ~ NOT

You will want to use the AND operator to execute the THEN statement if both expressions that are linked by AND are true, such as here:

IF (p1 GT 90) AND (f1 GT 90) THEN performance = 'excellent';

You will want to use the OR operator to execute the THEN statement if either expression that is linked by the OR is true, such as here:

IF (p1 GT 90) OR (f1 GT 90) THEN performance = 'very good';

And, you will want to use the NOT operator in conjunction with other operators to reverse the logic of a comparison:

IF p1 NOT IN (98, 99, 100) THEN performance = 'not excellent';

Now when we look at examples using these logical operators, why stop at just two ELSE statements? Let’s go crazy and program a bunch of them! One thing though — when we do, we have to be extra careful to make sure that our conditions are mutually exclusive. That is, we have to make sure that, for each observation in the data set, one and only one of the conditions holds. This most often means that we have to make sure that the endpoints of our intervals don’t overlap in some way.

Example

The following SAS program illustrates the use of several mutually exclusive conditions within an if-then-else statement. The program uses the AND operator to define the conditions. Again, when comparisons are connected by AND, all of the comparisons must be true in order for the condition to be true.

DATA grades;
    length overall $ 10;
   	input name $ 1-15 e1 e2 e3 e4 p1 f1;
    avg = round((e1+e2+e3+e4)/4,0.1);
         if (avg = .)                   then overall = 'Incomplete';
    else if (avg >= 90)                 then overall = 'A';
    else if (avg >= 80) and (avg < 90)  then overall = 'B';
    else if (avg >= 70) and (avg < 80)  then overall = 'C';
    else if (avg >= 65) and (avg < 70)  then overall = 'D';
    else if (avg < 65)                  then overall = 'F';	
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name avg overall;
RUN;
SAS Output

The SAS System

Obs name avg overall
1 Alexander Smith 78.8 C
2 John Simon . Incomplete
3 Patricia Jones 95.3 A
4 Jack Benedict 59.3 F
5 Rene Porter 81.0 B

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the letter grades have been assigned correctly. Also note how the program in general, and the if-then-else statement in particular, is formatted in order to make the program easy to read. The conditions and assignment statements are aligned nicely in columns and parentheses are used to help offset the conditions. Whenever possible ... okay, make that always ... format (and comment) your programs. After all, you may actually need to use them again in a few years. Trust me ... you'll appreciate it then! Note that:

  • First, the program calculates the student's overall average and rounds the result to the first decimal place. By using the definition to calculate the average, we ensure that a student who has missed an exam gets assigned a missing value for his or her overall average.
  • Note that there is an if statement to check for missing values. If the student's average is missing valued, then the grade should be incomplete. We will learn more about how SAS handles missing values later.
  • If the student's overall average is 90 or higher, then the assigned grade is an A.
  • If the student's overall grade is 80 or higher AND less than 90, then the student is assigned a B.
  • If the student's overall grade is 70 or higher AND less than 80, then the student is assigned a C.
  • If the student's overall grade is 65 or higher AND less than 70, then the student is assigned a D.
  • If the student's overall grade is less than 65, then the student is assigned an F.

Oh, one more point. You may have noticed, after the condition that takes care of missing values, that the conditions appear in order from A, B, ... down to F. Is the instructor treating the glass as being half-full as opposed to half-empty? Hmmm ... actually, the order has to do with the efficiency of the statements. When SAS encounters the condition that is true for a particular observation, it jumps out of the if-then-else statement to the next statement in the DATA step. SAS thereby avoids having to needlessly evaluate all of the remaining conditions. Hence, we have ourselves another good programming habit ... arrange the order of your conditions (roughly speaking, of course!) in an if-then-else statement so that the most common one appears first, the next most common one appears second, and so on. You'll also need to make sure that your condition concerning missing values appears first in the IF statement, otherwise SAS may bypass it.

Example

In the previous program, the conditions were written using the AND operator. Alternatively, we could have just used straightforward numerical intervals. The following SAS program illustrates the use of alternative intervals as well as the alternative syntax for the comparison operators. Note that you get the same output as the previous program.

DATA grades;
    length overall $ 10;
   	input name $ 1-15 e1 e2 e3 e4 p1 f1;
    avg = round((e1+e2+e3+e4)/4,0.1);
         if (avg EQ .)         then overall = 'Incomplete';
    else if (90 LE avg LE 100) then overall = 'A';
    else if (80 LE avg LT  90) then overall = 'B';
    else if (70 LE avg LT  80) then overall = 'C';
    else if (65 LE avg LT  70) then overall = 'D';
    else if (0  LE avg LT  65) then overall = 'F';
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name avg overall;
RUN;
SAS Output

The SAS System

Obs name avg overall
1 Alexander Smith 78.8 C
2 John Simon . Incomplete
3 Patricia Jones 95.3 A
4 Jack Benedict 59.3 F
5 Rene Porter 81.0 B

Example

Now, suppose an instructor wants to give bonus points to students who show some sign of improvement from the beginning of the course to the end of the course. Suppose she wants to add two points to a student's overall average if either her first exam grade is less than her third and fourth exam grade or her second exam grade is less than her third and fourth exam grade. (Don't ask why! I'm just trying to motivate something here.) The operative words here are "either" and "or". In order to accommodate the instructor's wishes, we need to take advantage of the OR comparison operator. When comparisons are connected by OR, only one of the comparisons needs to be true in order for the condition to be true. The following SAS program illustrates the use of the OR operator, the AND operator, and the use of the OR and AND operators together:

DATA grades;
   	input name $ 1-15 e1 e2 e3 e4 p1 f1;
    avg = round((e1+e2+e3+e4)/4,0.1);
         if    ((e1 < e3) and (e1 < e4)) 
            or ((e2 < e3) and (e2 < e4)) then adjavg = avg + 2;
    else adjavg = avg;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 avg adjavg;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 avg adjavg
1 Alexander Smith 78 82 86 69 78.8 78.8
2 John Simon 88 72 86 . . .
3 Patricia Jones 98 92 92 99 95.3 95.3
4 Jack Benedict 54 63 71 49 59.3 59.3
5 Rene Porter 100 62 88 74 81.0 83.0

First, inspect the program to make sure you understand the code. In particular, note that logical comparisons that are enclosed in parentheses are evaluated as true or false before they are compared to other expressions. In this example:

  • SAS first determines if e1 is less than e3 AND if e1 is less than e4
  • SAS then determines if e2 is less than e3 AND if e2 is less than e4
  • SAS then determines if the first bullet is true OR if the second bullet is true

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that, where appropriate, two points were added to the student's average (avg) to get an adjusted average (adjavg). Also, note that we didn't have to worry about programming for missing values here, because the student's adjusted average (adjavg) would automatically be assigned missing if his or her average (avg) was missing. SAS calls this "propagation of missing values."

5.10. Comparing Character Values

All of the if-then-else statement examples we’ve encountered so far involved only numeric variables. Our comparisons could just as easily involve character variables. The key point to remember when comparing character values is that SAS distinguishes between uppercase and lowercase letters. That is, character values must be specified in the same case in which they appear in the data set. We say that SAS is “case-sensitive.” Character values must also be enclosed in quotation marks.

Example

Suppose our now infamous instructor wants to identify those students who either did not complete the course or failed. Because SAS is case-sensitive, any if-then-else statements written to identify the students have to check for those students whose status is 'failed' or 'Failed' or 'FAILED' or ... you get the idea. One rather tedious solution would be to check for all possible "typings" of the word "failed" and "incomp" (for incomplete). Alternatively, we could use the UPCASE function to first produce an uppercase value, and then make our comparisons only between uppercase values. The following SAS program takes such an approach:

DATA grades;
    length action $ 7
           action2 $ 7;
    input name $ 1-15 e1 e2 e3 e4 p1 f1 status $;
         if (status = 'passed') then action = 'none';
    else if (status = 'failed') then action = 'contact';
    else if (status = 'incomp') then action = 'contact';
         if (upcase(status) = 'PASSED') then action2 = 'none';
    else if (upcase(status) = 'FAILED') then action2 = 'contact';
    else if (upcase(status) = 'INCOMP') then action2 = 'contact';
    DATALINES;
Alexander Smith  78 82 86 69  97 80 passed
John Simon       88 72 86  . 100 85 incomp
Patricia Jones   98 92 92 99  99 93 PAssed
Jack Benedict    54 63 71 49  82 69 FAILED
Rene Porter     100 62 88 74  98 92 PASSED
;
RUN;
 
PROC PRINT data = grades;
    var name status action action2;
RUN;
SAS Output

The SAS System

Obs name status action action2
1 Alexander Smith passed none none
2 John Simon incomp contact contact
3 Patricia Jones PAssed   none
4 Jack Benedict FAILED   contact
5 Rene Porter PASSED   none

Launch and run the SAS program. Review the output from the PRINT procedure to convince yourself that the if-then-else statement that involves the creation of the variable action is inadequate while the one that uses the UPCASE function to create the variable action2 works like a charm.

By the way, when making comparisons that involve character values, you should know that SAS considers a missing character value (a blank space ' ') to be smaller than any letter, and so the good habit of programming for missing values holds when dealing with character variables as well.

5.11. Performing Multiple Actions

All of the examples we’ve looked at so far have involved performing only one action for a given condition. There may be situations in which you want to perform more than one action.

Example

Suppose our instructor wants to assign a grade of zero to any student who missed the fourth exam, as well as notify the student that she has done so. The following SAS program illustrates the use of the DO-END clause to accommodate the instructors wishes:

DATA grades;
   	input name $ 1-15 e1 e2 e3 e4 p1 f1;
    if e4 = . then do;
        e4 = 0;
        notify = 'YES';
    end;
    DATALINES;
Alexander Smith  78 82 86 69  97 80
John Simon       88 72 86  . 100 85
Patricia Jones   98 92 92 99  99 93
Jack Benedict    54 63 71 49  82 69
Rene Porter     100 62 88 74  98 92
;
RUN;
 
PROC PRINT data = grades;
    var name e1 e2 e3 e4 p1 f1 notify;
RUN;
SAS Output

The SAS System

Obs name e1 e2 e3 e4 p1 f1 notify
1 Alexander Smith 78 82 86 69 97 80  
2 John Simon 88 72 86 0 100 85 YES
3 Patricia Jones 98 92 92 99 99 93  
4 Jack Benedict 54 63 71 49 82 69  
5 Rene Porter 100 62 88 74 98 92  

The DO statement tells SAS to treat all of the statements it encounters as one all-inclusive action until a matching END appears. If no matching END appears, SAS will hiccup. Launch and run the SAS program, and review the output of the PRINT procedure to convince yourself that the program accomplishes what we claim.

5.12. Exercises

  1. Use the following SAS data step to create the new variables Grade and Course defined below:

data school;
   input Age Quiz : $1. Midterm Final;
   /* Add you statements here */
datalines;
12 A 92 95
12 B 88 88
13 C 78 75
13 A 92 93
12 F 55 62
13 B 88 82
;

Using If-Then-Else statements, compute two new variables as follows:

  • Grade (numeric), with a value of 6 if Age is 12 and a value of 8 if Age is 13.

  • The quiz grades have numerical equivalents as follows: A = 95, B = 85, C = 75, D = 70, and F = 65. Using this information, compute a course grade (Course) as a weighted average of the Quiz (20%), Midterm (30%) and Final (50%).