SAS for the sassy and not so sassy
The Statistical Analysis System SAS is a very powerful for data analysis, though rather awkward to program. It requires you to shape your problem to the way SAS does things and is not nearly as flexible as other programming languages. Good beginning references are:
"The Little SAS Book" by Lora Delwiche and Susan Slaughter, SAS Institute, ISBN 1-55544-215-3 ***Highly recommended***
"Quick Start to Data Analysis with SAS" by Frank DiIorio and Kenneth Hardy, Duxbury press ISBN 0-534-23760-6
"The Little SAS Book" gives a better introduction to manipulating data while the "Quick Start .. " spends more time analyzing data using SAS PROC commands.
SAS programs and data sets can be found in N:\SAScourse. Feel free to experiment with these.
For online documentation log on to lan106. Type ‘sas’ at the prompt which
opens the SAS display manager, and choose the Help menu.
or point your browser to DOIT online documentation for SAS:
http://shelf.doit.wisc.edu/SASOnlineDocs/onldoc.htm
SAS web site: www.sas.com
Basic programming rules (must be obeyed):
Every SAS statement ends with a semicolon.
Variable and data set names can be up to 32 characters in length
Variable values can be numeric or character (up to 32768 characters)
Names must start with a letter or an underscore ( _ ).
Names can contain only letters, numerals and underscore. No $#!@& etc.
Always save programs and data files in "Unix" format (can use 'pc2unix' program).
Programming suggestions (strongly recommended):
COMMENT, COMMENT, COMMENT (* comments ;
or /* comments ; */ )
programmer's name, date written, any modifications,
what the programs does, input data sets, output data sets, descriptions of
data
steps throughout the program
Name permanent SAS data sets so that they can be linked to
the SAS program which created them
(e.g. SASPGM.INPUT created by program input.sas)
Consistently upper or lower case - usually SAS commands in upper
case. Below, I've used upper case for SAS commands, lower case for
variables and lower case with 'dat' appended for data sets.
Continue on next line (as long as words are not split in two) - good for readability
Although you can have many statements on same line best kept to one.
Statements can start in any column - use indentation to separate parts of program
creative use of:
Lists of variable names:
numbered: chan1 chan2 ... chan128 can be written as chan1 - chan128
(must be consecutive but can start and end anywhere)
named: y a c h r b, y -- b
(depends on order of variables in SAS data set)
SAS special name lists: _ALL_,
_CHARACTER_, _NUMERIC_
for example
MEAN(OF _NUMERIC_); PUT _CHARACTER_;
SAS data sets
The basic work unit in SAS is a DATA set consisting of variables and observations - much like a spreadsheet with variables arranged by columns and observations of these variables by rows. There are two types of variables Numeric and Character.
Variables
| ID | NAME | HEIGHT | WEIGHT | |
| 1 | 53 | Susan | 42 | 41 |
| 2 | 54 | Charlie | 46 | 55 |
| 3 | 55 | Calvin | 40 | 35 |
| 4 | 56 | Lucy | 46 | 52 |
| 5 | 57 | Dennis | 44 | . |
| 6 | 58 | 43 | 50 |
Missing character data is represented by blanks and missing numeric data by period (.).
Simple SAS program
SAS programs consist of two parts: DATA steps and PROC steps.
Let's multiply 24 times 3 in SAS. Even for this trivial task it is necessary to create a data set. The following code was typed into TextPad and saved in Unix format in multiply.sas. The program was run on lan104 by typing "sasb multiply.sas".
/* Simple program to multiply 24 times 3
written by LG for SAS course 4/8/03 */
DATA multdat;
num1 = 24;
num2 = 3;
prod12 = num1*num2;
PROC PRINT DATA = multdat;
A log file is created, multiply.log, which contains notes, error messages, number of observations and variables, number of output pages in list (.lst) file:
1 The SAS System 11:11 Tuesday, April 8, 2003
NOTE: Copyright (c) 1999 by SAS Institute Inc., Cary, NC, USA.
NOTE: SAS (r) Proprietary Software Version 8 (TS M0)
Licensed to UNIVERSITY OF WISCONSIN, Site 0002176032.
NOTE: This session is executing on the SunOS 5.6 platform.
This message is contained in the SAS news file, and is presented upon
initialization. Edit the files "news" in the "misc/base" directory to
display site-specific news and information in the program log.
The command line option "-nonews" will prevent this display.
NOTE: SAS initialization used:
real time 0.17 seconds
cpu time 0.13 seconds
1 /* Simple program to multiply 24 times 3
2 written by LG for SAS course 4/8/03 */
3 DATA multiplydat;
4 num1 = 24;
5 num2 = 3;
6 prod12 = num1*num2;
7
NOTE: The data set WORK.MULTIPLYDAT has 1 observations and 3 variables.
NOTE: DATA statement used:
real time 0.03 seconds
cpu time 0.03 seconds
8 PROC PRINT DATA = multiplydat;
NOTE: There were 1 observations read from the dataset WORK.MULTIPLYDAT.
NOTE: The PROCEDURE PRINT printed page 1.
NOTE: PROCEDURE PRINT used:
real time 0.05 seconds
cpu time 0.05 seconds
NOTE: SAS Institute Inc., SAS Campus Drive, Cary, NC USA 27513-2414
NOTE: The SAS System used:
real time 0.27 seconds
cpu time 0.21 seconds
output written to multiply.lst shown below:
The SAS System 11:11 Tuesday, April 8, 2003
1
Obs num1 num2
prod12
1 24
3
72
Now multiply a series of numbers (multiply1.sas):
/* Simple program to multiply several sets of numbers
and illustrate a numbered variable list
written by LG for SAS course 4/8/03 */
DATA multiply1dat;
INPUT num1 - num4;
prod1234 = num1*num2*num3*num4;
CARDS;
24 3 7 13
17 12 81 6
38 18 2 5
29 13 63 76
;
PROC PRINT DATA = multiply1dat;
output in multiply1.lst
The SAS System 09:25 Tuesday, April 8, 2003 1
Obs num1 num2 num3
num4 prod1234
1 24
3 7
13 6552
2 17
12 81
6 99144
3 38
18 2
5 6840
4 29
13 63
76 1805076
DATA step's built-in loop:
DATA steps execute line by line and observation by observation.

The data step includes a built-in loop which executes data step lines for each input observation:
The lines in the DATA step can contain most of the usual procedural programming constructs and commands such as:
ARRAY channel(128) ch1-ch128
Comparison operators: EQ (=), GT (>), LT (<), GE (>=), LE (<=), NE (~=), IN,
NOTIN (~IN)
Logical operators: AND (&), OR ( | )
IF THEN ELSE
FOR I=1 TO 128; DO; IF channel(I) LT 0 THEN channel(I) = .;
END;
logpwr = LOG(rawpwr);
See pages 70-71 of Little SAS Book for more complete list.
Getting data into SAS
CARDS; DATALINES; As shown
above these must be the last lines in the data statement with a semicolon
following the last line of data.
INFILE '/dc/larry/SAScourse/test.txt' DLM=',';
If data is tab-delimited can use DLM='09'x or
EXPANDTABS which replaces tab characters with spaces.
For long lines you may need LRECL=500;
To skip two lines use FIRSTOBS = 3;
To stop at line ten use OBS = 10;
If more than one observation per line use @@
By default SAS goes to next line of input file if not all
variables have been read. Use MISSOVER to prevent
this and have SAS put missing values
in unread variables for each line of input data.
From TextPad always save SAS programs or data files in Unix
format.
%wildcard(LOTSOFFILES, /dc/larry/SAScourse/test_*.txt);
INFILE LOTSOFFILES;
where LOTSOFFILES is a name given to represent all the files in the wildcard
list. SAS puts all the files together as though you had created one big
file by pasting the individual files together in a text editor like TextPad
The SET statement is used to input existing SAS
data sets:
DATA new-data-set;
SET existing-data-set;
Temporary versus Permanent SAS data sets
For the simple multiplication program:
DATA multiplydat;
num1 = 24;
num2 = 3;
product = num1*num2;
PROC PRINT DATA = multiplydat;
RUN;
SAS saves the data in a temporary file called WORK.multiplydat which exists only as long as SAS spends running this program. In order to save this data in a permanent file you need to define a LIBNAME which can be done as follows:
LIBNAME sasbook 'c:\mysaslib'
DATA sasbook.multiplydat;
num1 = 24;
num2 = 3;
product = num1*num2;
PROC PRINT DATA = sasbook.multiplydat;
where sasbook is the name you have chosen for your permanent SAS data set and 'c:\mysaslib' is the directory for your SAS data library. Note that you must give permanent SAS data sets a two part name consisting of the LIBNAME followed by a period then the data set name. Generally, we do our work in a saspgm directory created in a study folder so that our command looks like:
LIBNAME saspgm '.';
Note that we are currently running SAS version 8. If you have old
version 6 permanent SAS data sets they must be in a separate folder:
LIBNAME saspgm '.';
LIBNAME saspgmv6 './sasv6dat';
PROC PRINT DATA = saspgm.input;
PROC PRINT DATA = saspgmv6dat.oldinput;
Juggling data sets with SAS
This simple example illustrates creating two permanent SAS data sets and using the SET statement to input them successively (concatenate) into temporary data set for printing. Fun Park data from page 120 "The Little SAS Book" .
Program entry.sas:
/* This program creates two permanent SAS data sets
and illustrates concatenating them using the SET statement
written by LG for SAS course 4/8/03 */
/* set up permanent data library folder as current directory*/
LIBNAME saspgm '.';
/* create South entry data set */
DATA saspgm.sentrydat;
INPUT entrance $ passnum prtysize age;
CARDS;
S 43 3 27
S 44 3 24
S 45 3 2
;
/* create North entry data set */
DATA saspgm.nentrydat;
INPUT entrance $ passnum prtysize age lot;
CARDS;
N 21 5 41 1
N 87 4 33 3
N 65 2 67 1
N 66 2 7 1
;
/* combine data sets for printing */
DATA bothdat;
SET saspgm.sentrydat saspgm.nentrydat;
PROC PRINT;
TITLE 'Both files';
Output entry.lst:
Both files
Obs entrance passnum prtysize age lot
1 S
43 3
27 .
2 S
44 3
24 .
3 S
45 3
2 .
4 N
21 5
41 1
5 N
87 4
33 3
6 N
65 2
67 1
7 N
66 2
7 1
Now let's use some other SAS commands to output part of this data set.
The commands are:
KEEP = variable list
tells SAS which variables to keep
DROP = variable list
tells SAS which variables to drop
RENAME = (oldvar = newvar) tells SAS to rename certain variables
FIRSTOBS = n
tells SAS to start reading at observation n
OBS = n
tells SAS to stop reading at observation n
by replacing the last section of code shown above (entry1.sas):
Program entry1.sas:
/* program to subset the North and South entrance data
created by entry.sas. Written by LG for SAS course 4/8/03 */
LIBNAME saspgm '.';
/* combine data set with fewer variables and observations */
DATA nsentrydat (KEEP= entrance passnum prtysize);
SET saspgm.sentrydat (FIRSTOBS = 2) saspgm.nentrydat (OBS=
3);
DATA subsetdat (RENAME=(entrance = entr passnum=pnum);
SET nsentrydat;
PROC PRINT;
TITLE 'Both files subset';
Output entry1.lst:
Both files subset
Obs entr pnum prtysize
1 S 44
3
2 S 45
3
3 N 21
5
4 N 87
4
5 N 65
2
If we want to group observations by entrance for printing use the SAS BY
command (entry2.sas):
Program entry2.sas:
/* program to print the North and South entrance data
created by entry.sas sorted BY entrance
Written by LG for SAS course 4/8/03 */
LIBNAME saspgm '.';
DATA bothdat;
SET saspgm.sentrydat saspgm.nentrydat;
PROC SORT;
BY entrance;
PROC PRINT;
BY entrance;
TITLE 'Both files subset printed by entrance';
Output entry2.lst:
Both files subset printed by entrance
------------------ entrance=N ------------------
Obs passnum prtysize age lot
1 21
5 41 1
2 87
4 33 3
3 65
2 67 1
4 66
2 7
1
------------------ entrance=S ------------------
Obs passnum prtysize age lot
5 43
3 27
.
6 44
3 24
.
7 45
3 2
.
Entrance data and additional data collected after entering the Fun park (pages 122-123, LSB) can be combined using the SAS MERGE statement :
Program entry3.sas:
/* program to MERGE the North and South entrance data
created by entry.sas with new scream data
Written by LG for SAS course 4/8/03 */
LIBNAME saspgm '.';
DATA bothdat (DROP = lot);
SET saspgm.sentrydat saspgm.nentrydat;
/* need to sort by passnum for later MERGE */
PROC SORT;
BY passnum;
DATA screamsdat;
INPUT passnum scream;
DATALINES;
43 0
21 1
44 1
87 0
66 0
;
/* need to sort by passnum for later MERGE */
PROC SORT;
BY passnum;
DATA alldat;
MERGE bothdat screamsdat;
BY passnum;
PROC PRINT;
TITLE 'SAS Data Set All';
TITLE1 'Merge of Entrance and Screaming data';
Output entry3.lst:
SAS Data Set All
Merge of Entrance and Screaming data
Obs entrance passnum prtysize age scream
1 N
21 5
41 1
2 S
43 3
27 0
3 S
44 3
24 1
4 S
45 3
2 .
5 N
65 2
67 .
6 N
66 2
7 0
7 N
87 4
33 0
SAS's SUM and RETAIN statements can be used to access values from the previous observation (pages 82-83, LSB). Suppose a store wants to keep track of a running total and max/min values for daily sales:
Program sales.sas:
/* use RETAIN and SUM statements to access data from previous observations
to keep track of daily sales totals and overall max and min sales
written by LG for SAS course 4/8/03 */
DATA salesdat;
INPUT dailysales @@;
RETAIN dailysalesmax -99999 dailysalesmin 9999999 salestotal
0;
dailysalesmax = MAX(dailysalesmax,dailysales);
dailysalesmin = MIN(dailysalesmin,dailysales);
salestotal = sum(salestotal,dailysales);
CARDS;
350 460 230 375 525 200 400 350 175 280 600 340 230 175 450
330 540
;
PROC PRINT DATA = salesdat;
Note that the @@ in the INPUT command tells SAS that there are multiple
observations per line.
Output sales.lst:
Obs dailysales dailysalesmax
dailysalesmin salestotal
1 350
350
350
350
2 460
460
350
810
3 230
460
230
1040
4 375
460
230
1415
5 525
525
230
1940
6 200
525
200
2140
7 400
525
200
2540
8 350
525
200
2890
9 175
525
175
3065
10 280
525
175
3345
11 600
600
175
3945
12 340
600
175
4285
13 230
600
175
4515
14 175
600
175
4690
15 450
600
175
5140
16 330
600
175
5470
17 540
600
175
6010
SAS's automatic variable _N_ is always available during the DATA step, and FIRST.variable and LAST.variable are available if there is a BY statement (pages 141-142, LSB). Below is an example of how these work (walkers.sas):
program walkers.sas:
/* program to demonstrate FIRST.variable and LAST.variable
written by LG for SAS course 4/8/03 */
DATA walkers;
INPUT entry agegrp $ time @@;
CARDS;
54 youth 35.5 21 adult 21.6 6 adult 25.8 13 senior 29.0 38
senior 40.3 19 youth 39.6
3 adult 19.0 25 youth 47.3 11 adult 21.9 8 senior 54.3 41
adult 43.0 32 youth 38.6
;
/* sort by time so that placings can be determined */
PROC SORT;
BY time;
/* add placings using automatic variable _N_ */
DATA ordered;
SET walkers;
place = _N_;
PROC PRINT;
TITLE 'Results of walk';
/* now sort data by agegrp and time so that the first occurrence in each age
group
is the winner for that group */
PROC SORT;
BY agegrp time;
/* print this sorted data with FIRST.agegrp and LAST.agegrp values */
DATA printdat;
SET ordered;
BY agegrp;
firstvar = FIRST.agegrp;
lastvar = LAST.agegrp;
PROC PRINT DATA = printdat;
TITLE 'Show FIRST.variable LAST.variable';
DATA winners losers;
SET ordered;
BY agegrp;
IF FIRST.agegrp THEN OUTPUT winners;
IF LAST.agegrp THEN OUTPUT losers;
PROC PRINT DATA = winners;
TITLE 'Winners in each age group';
PROC PRINT DATA = losers;
TITLE 'Losers in each age group';
output walkers.sas:
Results of walk
Obs entry agegrp time
place
1 3
adult 19.0
1
2 21
adult 21.6
2
3 11
adult 21.9
3
4 6
adult 25.8
4
5 13
senior 29.0 5
6 54
youth 35.5
6
7 32
youth 38.6
7
8 19
youth 39.6
8
9 38
senior 40.3 9
10 41
adult 43.0
10
11 25
youth 47.3
11
12 8
senior 54.3 12
Show FIRST.variable LAST.variable
Obs entry agegrp time place
firstvar lastvar
1 3 adult
19.0 1
1 0
2 21 adult
21.6 2
0 0
3 11 adult
21.9 3
0 0
4 6 adult
25.8 4
0 0
5 41 adult
43.0 10
0 1
6 13 senior
29.0 5
1 0
7 38 senior
40.3 9
0 0
8 8 senior
54.3 12
0 1
9 54 youth
35.5 6
1 0
10 32 youth 38.6
7 0
0
11 19 youth 39.6
8 0
0
12 25 youth 47.3
11 0
1
Winners in each age group
Obs entry agegrp
time place
1 3
adult 19.0
1
2 13
senior 29.0
5
3 54
youth 35.5
6
Losers in each age group
Obs entry agegrp time
place
1 41
adult 43.0 10
2 8
senior 54.3 12
3 25
youth 47.3 11
Let's look at changing observations to variables with PROC TRANSPOSE (pages 140-141, LSB). This procedure may be useful for working with the BND files which are created by dopower. First a simple example to illustrate how to set up.
DATA baseball;
INPUT team $ player type $ entry;
CARDS;
Garlics 10 salary 43000
Peaches 8 salary 38000
Garlics 21 salary 51000
Peaches 10 salary 47500
Garlics 10 batavg .281
Peaches 8 batavg .252
Garlics 21 batavg .265
Peaches 10 batavg .301
;
PROC SORT;
BY team player;
PROC PRINT;
TITLE 'Baseball data after sorting and before transposing';
* Transpose data so salary and batavg are variables;
PROC TRANSPOSE;
BY team player;
ID type;
VAR entry;
PROC PRINT;
TITLE 'Baseball data after transposing';
RUN;
Baseball data after sorting and before transposing
Obs team player type
entry
1 Garlics 10
salary 43000.00
2 Garlics 10
batavg 0.28
3 Garlics 21
salary 51000.00
4 Garlics 21
batavg 0.27
5 Peaches 8
salary 38000.00
6 Peaches 8
batavg 0.25
7 Peaches 10
salary 47500.00
8 Peaches 10
batavg 0.30
Baseball data after transposing
Obs team player _NAME_
salary batavg
1 Garlics 10
entry 43000 0.281
2 Garlics 21
entry 51000 0.265
3 Peaches 8
entry 38000 0.252
4 Peaches 10
entry 47500 0.301
Now let's look at some real real data from the BND files for LNT358 (a
subject which showed lots of electrolyte bridging effects). First the
following program (inputBND.sas) reads in the eight baseline BND files and
creates a permanent SAS data set for further work:
LIBNAME SASPGM ".";
%wildcard(NETEEG, /dc/larry/SAScourse/LNT*/LNT*_NO60.BND) ;
DATA SASPGM.BND (DROP = LOBAND HIBAND);
INFILE NETEEG;
INPUT SESSION CHANNEL REF $ BAND $ CONDTN $ TRIAL LOBAND
HIBAND
RAWPWR LOGPWR EEGDUR CHUNKS ;
One of the challenges of working with SAS is that data sets are generally much too large to inspect visually as we've been doing for these simple examples. Checking inputBND.log indicates that the resulting data file is the right size:
NOTE: 30720 records were read from the infile NETEEG.
The minimum record length was 49.
The maximum record length was 83.
NOTE: The data set SASPGM.BND has 30720 observations and 10 variables.
We dropped two variables from the twelve in the input statement so 10 variables is correct. The input BND files contained 128 channels x 10 frequency bands x 3 references x 8 baseline files = 30720 observations.
One way to simplify working with this data is to put the values for all 128 channels on a single line (i.e. in a single observation). The transpose procedure just described looks like an easy way to accomplish this (transposeBND.sas):
LIBNAME SASPGM ".";
DATA tmpbnd;
/* use the permanent SAS data set created above */
SET SASPGM.BND;
/* keep only Alpha band values for this example*/
IF BAND = "Alpha";
/* sort in preparation for transposing "BY" these variables*/
PROC SORT;
BY SESSION REF CONDTN TRIAL;
PROC TRANSPOSE;
BY SESSION REF CONDTN TRIAL;
ID CHANNEL;
VAR RAWPWR LOGPWR EEGDUR CHUNKS;
PROC PRINT;
TITLE 'Transposed BND file for LNT358';
RUN;
The output looks like:
Transposed BND file for LNT358
Obs SESSION REF CONDTN TRIAL _NAME_
_1 _2
_3 _4
_5
1 358 AVEALL
EC 1
RAWPWR 111.564
104.675 81.455 37.736
24.759
2 358 AVEALL
EC 1
LOGPWR 2.048
2.020 1.911
1.577 1.394
3 358 AVEALL
EC 1
EEGDUR 59.308
60.000 60.000
60.000 60.000
4 358 AVEALL
EC 1
CHUNKS 115.000
119.000 119.000 119.000
119.000
5 358 AVEALL
EC 2
RAWPWR 103.897
94.566 74.901
36.337 23.257
6 358 AVEALL
EC 2
LOGPWR 2.017
1.976 1.875
1.560 1.367
7 358 AVEALL
EC 2
EEGDUR 60.000
60.000 60.000
60.000 60.000
8 358 AVEALL
EC 2
CHUNKS 119.000
119.000 119.000
119.000 119.000
9 358 AVEALL
EC 3
RAWPWR 119.509
102.975 85.056
39.348 25.573
10 358 AVEALL
EC 3
LOGPWR 2.077
2.013 1.930
1.595 1.408
11 358 AVEALL
EC 3
EEGDUR 60.000
60.000 60.000
60.000 60.000
12 358 AVEALL
EC 3
CHUNKS 119.000
119.000 119.000
119.000 119.000
13 358 AVEALL
EC 4
RAWPWR 107.209 96.479
82.778 36.885
24.515
14 358 AVEALL
EC 4
LOGPWR 2.030
1.984
1.918 1.567
1.389
...
NOTE: There were 3072 observations read from the dataset WORK.TMPBND.
NOTE: The data set WORK.TRNPBND has 96 observations and 133 variables
Since only Alpha band (1 of 10) was kept 3072 of the original 30720 were read. Transposing the data by RAWPWR, LOGPWR, EEGDUR, and CHUNKS reduced 128 observations to 4 so the output file has 3072 x 4/128 = 96 observations
We still need to do some juggling and renaming to get the values for RAWPWR,
LOGPWR, EEGDUR, and CHUNKS on the same line. The following code was added
after the PROC TRANSPOSE (transposeBND1.sas):
DATA rawpwr (RENAME = (_1-_128 = RAWPWR1-RAWPWR128))
logpwr (RENAME =
(_1-_128 = LOGPWR1-LOGPWR128))
eegdur (RENAME =
(_1-_128 = EEGDUR1-EEGDUR128))
chunks (RENAME = (_1-_128
= CHUNKS1-CHUNKS128));
SET trnpbnd;
IF _NAME_ = "RAWPWR" THEN
OUTPUT rawpwr;
IF _NAME_ = "LOGPWR" THEN
OUTPUT logpwr;
IF _NAME_ = "EEGDUR" THEN
OUTPUT eegdur;
IF _NAME_ = "CHUNKS" THEN
OUTPUT chunks;
DATA SASPGM.INPUT (DROP=_NAME_);
MERGE rawpwr logpwr eegdur chunks;
PROC PRINT;
TITLE 'Transposed and extended BND file for LNT358';
RUN;
Transposed and extended BND file for LNT358
Obs SESSION REF CONDTN TRIAL RAWPWR1 RAWPWR2
RAWPWR3 RAWPWR4 RAWPWR5
RAWPWR6
1 358 AVEALL
EC 1
111.564 104.675
81.455 37.736
24.759 16.094
2 358 AVEALL
EC 2
103.897 94.566
74.901 36.337
23.257 17.447
3 358 AVEALL
EC 3
119.509 102.975
85.056 39.348
25.573 15.834
4 358 AVEALL
EC 4
107.209 96.479
82.778 36.885
24.515 12.774
5 358 AVEALL
EO 1
14.288 15.422
13.890 5.293
3.911
1.727
6 358 AVEALL
EO 2
16.265 15.806
15.911 5.729
4.208
1.669
7 358 AVEALL
EO 3
17.098 12.884
15.091 4.208
3.121
1.731
8 358 AVEALL
EO 4
17.249 16.438
15.081 6.015
4.672
2.098
...
NOTE: The data set SASPGM.INPUT has 24 observations and 516 variables.
There are 8 trials by 3 references (AVEALL, AVEMAST and Cz) equals 24
observations by RAWPWR, LOGPWR, EEGDUR, and CHUNKS 1-128 plus SESSION, REF,
CONDTN, TRIAL equals 516 variables.