```
DATA out_Asia;
set sashelp.cars(where=(origin='Asia'));
run;
DATA out_Europe;
set sashelp.cars(where=(origin='Europe'));
run;
DATA out_USA;
set sashelp.cars(where=(origin='USA'));
run;
```

I'm going to admit right now that this isn't the most efficient or elegant method, but it's something that most beginning SAS programmers could easily come up with.
Writing the above program is easy, especially since there are only 3 different values for Origin and I've memorized their values. But if there are more discrete values for the "split-by" column, the task could involve much more typing and has a high possibility for error. This is when I usually use PROC SQL to generate the code for me.
If you've read my article about implementing BY processing for an entire SAS program, you know that you can use PROC SQL and SELECT INTO to place data values from a data set into a macro variable. For example, consider this simple program:
```
proc sql;
select distinct ORIGIN into :valList separated by ',' from SASHELP.CARS;
quit;
```

It creates a macro variable VALLIST that contains the comma-separated list: "Asia,Europe,USA".
But we can use SAS functions to embellish that output, and create ```
/* define which libname.member table, and by which column */
%let TABLE=sashelp.cars;
%let COLUMN=origin;
proc sql noprint;
/* build a mini program for each value */
/* create a table with valid chars from data value */
select distinct
cat("DATA out_",compress(&COLUMN.,,'kad'),
"; set &TABLE.(where=(&COLUMN.='", &COLUMN.,
"')); run;") into :allsteps separated by ';'
from &TABLE.;
quit;
/* macro that includes the program we just generated */
%macro runSteps;
&allsteps.;
%mend;
/* and...run the macro when ready */
%runSteps;
```

Here are the highlights from the PROC SQL portion of the program:
- SELECT DISTINCT ensures that the results include just one record for each unique value of the variable.
- The CAT function concatenates a set of string values together. Note that CATX and CATS and CATT -- other variations of this function -- will trim out white space from the various string elements. In this case I want to keep any blank characters that occur in the data values because we're using those values in an equality check.
- The program calculates a name for each output data set by using each data value as a suffix ("OUT_
*dataValue*"). SAS data set names can contain only numbers and letters, so I use the COMPRESS function to purge any invalid characters from the data set name. The**'kad'**options on COMPRESS tell it to**keep**only**alpha**and**digit**characters. - The resulting program statements all end up in the &ALLSTEPS macro variable. I could just reference the &ALLSTEPS variable in the body of the SAS program, and SAS would run it as-is. Instead I chose to wrap it in the macro
**%runSteps**. This makes it a little bit easier to control the scope and placement of the executable SAS program statements.

- Quantity of observations (split a 3-million-record table into 3 1-million-record tables)
- Rank or percentiles (based on some measure, put the top 20% in its own data set)
- Time span (break up a data set by year or month, assuming the data records contain a date or datetime variable)

```
if c=5 then put "c=5 is TRUE";
else put "c=5 is FALSE";
```

In the SAS/IML language, the situation can be more complicated because a variable is usually a matrix or a vector. You can use matrices in logical expressions, but when `c` is not a scalar quantity, what does the statement `if c=5 then...` mean? What happens when some of the elements of `c` are 5, but other elements are not?

The following SAS/IML example illustrates the situation:

```
proc iml;
c = {5 5 6};
if c=5 then
print "c=5 is TRUE";
else
print "c=5 is FALSE";
```

According to the output, the logical expression `c=5` evaluates to FALSE.
This result can be understood by reading the documentation for the IF-THEN/ELSE statement, which says, "when the condition to be evaluated is a matrix expression, ...
this evaluation is equivalent to using the ALL function." In other words, the IF-THEN/ELSE statement is equivalent to the following:

```
if all(c=5) then
print "all(c=5) is TRUE";
else
print "all(c=5) is FALSE";
```

The ALL function evaluates to TRUE when all of the elements in a matrix are nonzero and nonmissing.
As I recently mentioned, you can use the RESET PRINTALL statement to see temporary matrices that SAS/IML creates when it evaluates logical expressions. The expression `c=5` results in the temporary matrix `{1 1 0}`. The ALL function returns 0 (FALSE) for that matrix.

If you want a condition to evaluate to TRUE if *any* element in a matrix satisfies a criterion, then use the ANY function explicitly, as follows:

```
if any(c=5) then
print "any(c=5) is TRUE";
else
print "any(c=5) is FALSE";
```

The takeaway lesson is that a matrix expression can be used in an IF-THEN/ELSE statement in the SAS/IML language. The THEN condition will be executed when all of the elements in the matrix satisfy the expression. The ELSE condition will be executed if one or more elements do not satisfy the expression.

]]>- Fun and effective: Teaching statistics with JMP by Anne Milley
- #OneLessPie chart on Pi Day by Xan Gregg
- Why spreadsheets can lead to error - part 1 by Charles Pirrello
- An eggciting designed eggsperiment by Ryan Lekivetz
- Determining chemical concentration with standard addition: An application of linear regression in JMP by Eric Cai
- How it works: Interactive HTML in JMP 11 by Heman Robinson
- The eggciting results of my designed eggsperiment by Ryan Lekivetz
- Digging into my diet and fitness data by Shannon Conners
- Music library visualizations by Louis Valente
- JMP Pro for linear mixed models - part 1 by Jian Cao