Thursday, April 17, 2008

SAS Array

Defining an Array

data charity(drop=qtr);
set prog2.donate;
array Contrib{4} Qtr1 Qtr2 Qtr3 Qtr4;
do qtr =1 to 4
Contrib{qtr} = Contrib{qtr} + 1.25;
end;
Run;


Proc Print data=percent noobs;
var ID percent1-percent4;
format percent1-percent4 percent6.;
run;

data change(drop=i);
set prog2.donate;
array Contrib{4} Qtr1-Qtr4;
array Diff{3};
do i =1 to 3;
Diff{i} = Contrib{i+1} - Contrib{i};
end;
run;

data compare(drop qtr goal1-goal4);
set prog2.donate;
array contrib{4} qtr1-qtr4;
array diff{4};
array goal{4} goal1-goal4 (10,15,5,10);
do qtr = 1 to 4;
diff{qtr} = contrib{qtr} - goal{qtr};
end;
run;

data rotate(drop=qtr1-qtr4);
set prog2.donate;
array contrib{4} qtr1-qtr4;
do qtr 1 to 4;
amount = contrib{qtr};
output;
end;
run;

Thursday, April 10, 2008

The Iterative DO Statement

do Month='JAN','FEB','MAR';
do Fib=1,2,3,5,8,13,21;
do i=Var1,Var2,Var3;
do j=BeginDate to Today() by 7;
do k=Test1-Test50;

Performing Repetitive Calculations
On January 1 of each year, $5,000 is invested in an account. Determine the value of the account after three years based on a constant annual interest rate of 7.5 percent.

data invest;
do Year=2001 to 2003;
Capital+5000;
Capital+(Capital*.075);
end;
run;

OUTPUT:
proc print data=invest noobs;
run;
Year Capital

2004 17364.61


BUT
Generate a separate observation for each year.
data invest;
do Year=2001 to 2003;
Capital+5000;
Capital+(Capital*.075);
output;
end;
run;

proc print data=invest noobs;
run;

OUTPUT:
Year Capital

2001 5375.00
2002 11153.13
2003 17364.61


prog2.growth
Num
Division Emps Increase

APTOPS 205 0.075
FINACE 198 0.040
FLTOPS 187 0.080


data forecast;
set prog2.growth(rename=(NumEmps=NewTotal));
/* COPY SAS dataset from prog2.growth, and change the NumEmps variable name to NewTotal*/
do Year=1 to 3;
NewTotal=NewTotal*(1+Increase);
output;
end;
run;

You can use DO WHILE and DO UNTIL statements to stop the loop when a condition is met rather than when the index variable exceeds a specific value.

The DO WHILE statement executes statements in a DO loop while a condition is true.
DO WHILE (expression);

END;

The DO UNTIL statement executes statements in a DO loop until a condition is true.
DO UNTIL (expression);

END;

Determine the number of years it would take for an account to exceed $1,000,000 if $5,000 is invested annually at 7.5 percent.

data invest;
do until(Capital>1000000);
Year+1;
Capital+5000;
Capital+(Capital*.075);
end;
run;

proc print data=invest noobs;
run;

OUTPUT:
Capital Year

1047355.91 38

You can combine DO WHILE and DO UNTIL statements with the iterative DO statement.
Determine the return of the account again. Stop the loop if 25 years is reached or more than $250,000 is accumulated.

data invest;
do Year=1 to 25 until(Capital>250000);
Capital+5000;
Capital+(Capital*.075);
end;
run;
proc print data=invest noobs;
run;

OUTPUT:
Year Capital

21 255594.86

Nested DO Loops
data invest(drop=Quarter);
do Year=1 to 5;
Capital+5000;
do Quarter=1 to 4;
Capital+(Capital*(.075/4));
end;
output;
end;
run;

proc print data=invest noobs;
run;

OUTPUT:
Year Capital

1 5385.68
2 11186.79
3 17435.37
4 24165.94
5 31415.68

The DATASETS Procedure

You can use the DATASETS procedure to modify a variable’s
name
label
format
informat.

PROC DATASETS LIBRARY=libref ;
MODIFY SAS-data-set ;
RENAME old-name-1=new-name-1
<. . . old-name-n=new-name-n>;
LABEL variable-1='label-1' <. . . variable-n='label-n'>;
FORMAT variable-list-1 format-1 <. . . variable-list-n format-n>;
INFORMAT variable-list-1 informat-1 <. . . variable-list-n informat-n>;
RUN;

Use the DATASETS procedure to change the name of the variable Dest to Destination.
Look at the attributes of the variables in the ia.dfwlax data set.

proc contents data=ia.dfwlax;
run;

Rename the variable Dest to Destination.
proc datasets library=ia;
modify dfwlax;
rename Dest=Destination;
run;

-----Alphabetic List of Variables and Attributes-----

# Variable Type Len Pos
--------------------------------------
2 Date Char 8 19
3 Destination Char 3 27
5 Economy Num 8 8
4 FirstClass Num 8 0
1 Flight Char 3 16

Permanent Variable Attributes

Assign labels and formats in the DATA step.

libname ia 'SAS-data-library';
data ia.dfwlax;
infile 'raw-data-file';
input @1 Flight $3. @4 Date mmddyy8.
@12 Dest $3. @15 FirstClass 3.
@18 Economy 3.;
format Date mmddyy10.;
label Dest='Destination'
FirstClass='First Class Passengers'
Economy='Economy Passengers';
run;

Examine the descriptor portion of the ia.dfwlax data set.

proc contents data=ia.dfwlax;
run;

OUTPUT
-----Alphabetic List of Variables and Attributes-----

# Variable Type Len Pos Format Label
----------------------------------------------------------------
2 Date Num 8 0 MMDDYY10.
3 Dest Char 3 27 Destination
5 Economy Num 8 16 Economy Passengers
4 FirstClass Num 8 8 First Class Passengers
1 Flight Char 3 24

Override Permanent Attributes
Use a FORMAT statement in a PROC step to temporarily override the format stored in the data set descriptor.

proc print data=ia.dfwlax label;
format Date date9.;
run;

the compilation phase

At compile time, SAS creates
1. an input buffer to hold the current raw data file record that is being processed
2. a program data vector (PDV) to hold the current SAS observation
3. the descriptor portion of the output data set.

The PDV contains two automatic variables that can be used for processing but which are not written to the data set as part of an observation:
_N_ counts the number of times that the DATA step begins to execute
_ERROR_ signals the occurrence of an error that is caused by the data during
execution.
0 is the default which means there is no error.
1 there is one or more errors.

During the compilation phase, SAS also scans each statement in the DATA step, looking for syntax errors. Syntax errors include:
1. Missing or misspelled keywords
2. Invalid variable names
3. Missing or invalid punctuation
4. Invalid options

Summary of the compilation phase
1. During the compilation phase, the input buffer is created to hold a record from the external file.
2. The PDV is created to hold the current observation
3. The descriptor portion of the SAS data set is created.

Thursday, April 3, 2008

PROC Functions

SAS functions
perform arithmetic operations
compute sample statistics (for example: sum, mean, and standard deviation)
manipulate SAS dates and process character values
perform many other tasks.

Sample statistics functions ignore missing values.

data onboard;
set work.pilotdata; (copy from dataset)
Total=sum(FirstClass,Economy);
run;

avgX = mean(of x1-x10);
stdX = std(of x1-x10);
minX = min(of x1-x10);
maxX = max(of x1-x10);
rangeX = range(of x1-x10);


Other useful sample statistic functions are:

MAX(argument,...) returns the largest value

MIN(argument,...) returns the smallest value

MEAN(argument,...) returns the arithmetic mean (average)

N(argument,....) returns the number of nonmissing arguments

NMISS(argument,...) returns the number of missing values

STD(argument,...) returns the standard deviation

STDERR(argument,...) returns the standard error of the mean

VAR(argument,...) returns the variance

Special WHERE

Use special operators in the WHERE statement to subset data.

LIKE selects observations by comparing character values to specified patterns.
A percent sign (%) replaces any number of characters.
An underscore (_) replaces one character.

where Code like 'E_U%';

Selects observations where the value of Code begins with an E, followed by a single character, followed by a U, followed by any number of characters.

The sounds like (=*) operator selects observations that contain spelling variations of the word or words specified.

where Name=*'SMITH';

Selects names like SMYTHE and SMITT.

IS NULL or IS MISSING selects observations in which the value of the variable is missing.

where Flight is missing;
where Flight is null;

Identifying Observations - ID (suppress OBS) v.s. NOOBS + BY-ID Group

Use the ID statement to identify observations.
Combine the BY and ID statements to produce special formatting.

proc print data=ia.empdata;
id JobCode;
var EmpID Salary;
run;

When the ID and BY statements specify the same variable,
the Obs column is suppressed
the BY line is suppressed
the ID/BY variable prints in the leftmost column
each ID/BY value only prints at the start of each BY group (and on the subtotal line, if a SUM statement is used).

Specify JobCode in the BY and ID statements to change the report format.

proc sort data=ia.empdata out=work.empdata;
by JobCode;
run;
proc print data=work.empdata;
by JobCode;
id JobCode;
sum Salary;
run;

Sorting SAS DataSet - PROC PRINT - SUM function + PageBreak

proc print data=ia.empdata noobs;
var JobCode EmpID Salary;
sum Salary;
run;

To request subgroup totals in PROC PRINT, the observations in the data set must be grouped.

The SORT procedure
rearranges the observations in a SAS data set
can create a new SAS data set containing the rearranged observations
can sort on multiple variables
can sort in ascending (default) or descending order
does not generate printed output
treats missing values as the smallest possible value.

Printing Subtotals and Grand Totals

Print the data set grouped by JobCode with a subtotal for the Salary column for each JobCode.

proc sort data=ia.empdata out=work.empdata;
by JobCode;
run;
proc print data=work.empdata;
by JobCode;
sum Salary;
run;

Page Breaks
Use the PAGEBY statement to put each subgroup on a separate page.

proc print data=work.empdata;
by JobCode;
pageby JobCode;
sum Salary;
run;

FILENAME vs LIBNAME

Using LIBNAME statement to reference a SAS data library

Libname libref 'C:\data'
libref.filename;


Usinga FILENAME statement to reference an external file

FIlename fileref 'C:\data\hw1.dat';
infile fileref;

PROC FORMAT

DATA HW1;
INFILE "D:\temp\files\hw1.txt"
DELIMITER=' ' /* or DLM=' '*/
MISSOVER
DSD
/* DSD means Delimiter-Sensitive Data, which does three things for you
First, it ignores delimiters in data values enclosed in quotation marks
Second, it does not read quotation marks as part of the data value
Third, it treats two delimiters in a row as a missing value.
DSD option assumes that delimiter is a comma. If your delimiter is not a comma then
you can use DELIMITER= option with the DSD option to specify the delimiter
*/
;
INPUT
SampleID
CaseControl $
Gender $
Race $
Age
NoCig
Multivitamins
Calcium
TumorICD9 $
FamilyHistory $
HRT $
Height
Weight;
BMI = (Weight*0.45)/((Height*0.0254)**2);
Proc format;
value Mul 1='never' 2='former' 3='current';
value Cal 1='never' 2='former' 3='current';
RUN;

proc print data = hw1 LABEL;
TITLE1 "CS133/BIOT133 - Introduction to SAS Programming";
TITLE2 "Homework #1";
LABEL
SampleID = "Sample ID"
CaseControl = "Case/Control"
Gender = "Gender"
Race = "Race"
Age = "Age"
NoCig = "Number of cigarettes smoked/day"
Multivitamins = "Multivitamins taken"
Calcium = "Calcium supplements taken"
TumorICD9 = "Tumor site by ICD9 code"
FamilyHistory = "Family History"
HRT = "HRT use"
Height = "Height in inches"
Weight = "Weight in pounds"
;
FORMAT Multivitamins Mul. Calcium Cal. BMI 2. ;
FOOTNOTE1 "Student - Yuan-Kai Huang";
FOOTNOTE2 "April 2, 2008";
run;

Thursday, March 20, 2008

Title, footnote, label, format, where

data pilotdata;
infile 'D:\SAS_Data\pilot.txt';
input ID $ 1 -6
firstname $ 7 - 19
lastname $ 20 - 34
jobcode $ 35 - 41
salary 42 -47
category $ 48 - 50;
Bonus = Salary * 0.1;
If jobcode = 'PILOT1' then
NewSalary = salary * 1.05;
Else If jobcode = 'PILOT2' then
NewSalary = salary * 1.07;
Else If jobcode = 'PILOT3' then
NewSalary = salary * 1.09;
run;
proc print data = pilotdata label;
title1 'International Airlines';
title2 'Employee Information';
label firstname = 'First Name'
lastname = 'Last Name'
jobcode = 'Job Code';
Format NewSalary Dollar10.;
WHERE jobcode = 'PILOT1';
footnote1 'Here is footnote 1';
footnote2 'Here is footnote 2';
run;

proc print data = pilotdata split = '*';
title1 'International*Airlines';
title2 'Employee Information';
label firstname = 'First*Name'
lastname = 'Last Name'
jobcode = 'Job Code';
run;

PUT, INPUT, and SUBSTR

/* input() function ---------------------Convert to Numberic
newVar = INPUT(oldVar, format);

put() function -----------------------Convert to Character
newVar = PUT(oldVar, format);

substr() function
*/

Data num;
A = 5;
B = '5';
C = A*B;
D = A*newB;

newB = input(B, 1.);
E = newB;
F = A*newB;

G = 98;
newD = put(G, 2.);

H1 = substr(newD, 2, 1);
H2 = substr('1998', 2);
run;

proc print data=num;
title "Data=put_input_substr";
run;


(OUTPUT)
Obs A B C D newB E F G newD H1 H2
1 5 5 25 . 5 5 25 98 98 8 998

Read missing values

/* By default - FLOWOVER; It will go next value and pick next value. This example shows missing the last two values - 3.4 and 3.5

(OUTPUT)
Obs A1 A2 A3 A4 A5
1 1.1 1.2 1.3 1.4 1.5
2 2.1 2.2 3.1 3.2 3.3
*/

DATA A_FLOWOVER;
INFILE CARDS FLOWOVER; /*DEFAULT*/
INPUT A1-A5;
CARDS;
1.1 1.2 1.3 1.4 1.5
2.1 2.2
3.1 3.2 3.3 3.4 3.5
;

PROC PRINT data=A_FLOWOVER;
title "Data=A_FLOWOVER";
RUN;

/* MISSOVER; it will skip the missing values in the line and grab next line

(OUTPUT)
Obs A1 A2 A3 A4 A5
1 1.1 1.2 1.3 1.4 1.5
2 2.1 2.2 . . .
3 3.1 3.2 3.3 3.4 3.5
*/

DATA B_MISSOVER;
INFILE CARDS MISSOVER;
INPUT A1-A5;
CARDS;
1.1 1.2 1.3 1.4 1.5
2.1 2.2
3.1 3.2 3.3 3.4 3.5
;

PROC PRINT data=B_MISSOVER;
title "Data=B_MISSOVER";
RUN;

/* STOPOVER; After you execute, the program will read the data till there is any missing data

(OUTPUT)
Obs A1 A2 A3 A4 A5
1 1.1 1.2 1.3 1.4 1.5
*/

DATA C2_STOPOVER;
INFILE CARDS STOPOVER;
INPUT A1-A5;
CARDS;
1.1 1.2 1.3 1.4 1.5
2.1 2.2
3.1 3.2 3.3 3.4 3.5
;

PROC PRINT data=C2_STOPOVER;
title "Data=C2_STOPOVER";
RUN;

Proc Contents

To explore the descriptor portion of a SAS data set and list of variables and attributes

Proc Contents Data = work.pilotdata;
Run;

Use the _ALL_ keyword to list all the SAS files in the library and the NODS option to suppress the descriptor portions of the data sets.

proc contents data = sasuser._all_ NODS;
run;

NODS must be used in conjunction with the keyword _ALL_.

Monday, March 17, 2008

PROC PRINT LABEL-SPLIT, WHERE

CONTAINS - selects observations that include ? the specified substring.

where LastName ? 'LAM';

OUTPUT: (LAMBERT, BELLAMY, and ELAM are selected.)


proc print data=tempemp split='*';
id jobcode;
by jobcode;
var gender salary;
sum salary;
label jobcode='Job Code*========'
gender='Gender*======'
salary='Annual Salary*=============';
format salary dollar11.2;
where jobcode in ('PT1','PT2');
title 'Expenses Incurred for';
title2 'Salaries for Pilots';
run;

id jobcode;
The ID statement identifies observations by using the formatted values of the variables that you list instead of by using observation numbers.

sum salary;
The SUM statement totals values of numeric variables. Here the SUM statement totals the values of Salary for each BY group and for the whole report.
label jobcode='Job Code*========'
gender='Gender*======'
salary='Annual Salary*=============';

The LABEL statement associates a label with each variable for the duration of the PROC PRINT step. When you use SPLIT= in the PROC PRINT statement, the procedure uses labels for column headings.
format salary dollar11.2;

The FORMAT statement assigns the DOLLAR12.2 format to Salary for this report.
where jobcode in ('PT1','PT2');

The WHERE statement selects only observations where the value of Jobcode is either PT1 or PT2.

Saturday, March 15, 2008

PROC PRINT - NOOBS option

proc print data=test noobs;

The PROC PRINT step prints the data set, which contains one observation and three variables. The NOOBS option suppresses observation numbers in the output.

/*************************************/
/* print the sorted data set */
/*************************************/
proc print data=tempemp split='*';
id jobcode;
by jobcode;
var gender salary;
sum salary;
label jobcode='Job Code*========'
gender='Gender*======'
salary='Annual Salary*=============';
format salary dollar11.2;
where jobcode in ('PT1','PT2');
title 'Expenses Incurred for';
title2 'Salaries for Pilots';
run;

Thursday, March 13, 2008

Work with SAS dates and times

SAS Date Value - Jan. 1, 1960

SAS stores date value as numeric values while SAS date is stored as numbers.

SAS stores dates and times as single, unique numbers so that you can use them in programs like any other numeric variable:

A SAS date value is a value that represents the number of days between January 1, 1960, and a specified date. SAS can perform calculations on dates ranging from A.D. 1582 to A.D. 19,900. Dates before January 1, 1960, are negative numbers; dates after are positive numbers.

/*************************************/
/* set system options for report */
/*************************************/
options nodate nonumber;
options nodate pageno=1 linesize=64 pagesize=60;

/*************************************/
/* create temporary data set */
/*************************************/
data test;
Time1=86399;
format Time1 datetime.;
Date1=86399;
format Date1 date.;
Time2=86399;
format Time2 timeampm.;
Date1Month=month(Date1);
run;

/*************************************/
/* OUTPUT */
/*************************************/

The SAS System

Obs Time1 Date1 Time2 Date1Month

1 01JAN60:23:59:59 20JUL96 11:59:59 PM 7

Subset data

/*************************************/
/* select observations and variables */
/*************************************/
data subset1;
set admit;
if fee>= 124.80 & sex = 'M';
keep id name age weight;
run;

The KEEP statement specifies that only the variables ID, Name, Age, and Weight appear in the subset data. You can use the DROP statement instead if more variables are kept than dropped.

/*************************************/
/* subset data, perform processing, */
/* and subset variables again */
/*************************************/
data subset2(keep=id sex kgweight);
set admit(drop=name date);
if actlevel='LOW' and age>40;
KgWeight=weight/2.2;
run;

The DROP= data set option in the SET statement prevents the variables Name and Date from being read from the input data set (and therefore from appearing in the output data set).

Create and redefine variables

/*************************************/
/* create and redefine variables */
/* with assignment, function */
/*************************************/
data diabetes_female;
set diabetes;
if sex='F';
GlucoseChange=postglucose-fastglucose;
fastglucose=fastglucose+fastglucose*.10;
AvgGlucose=mean(postglucose,fastglucose);
run;

/*************************************/
/* create variables with LENGTH */
/*************************************/
data PatientAccounts;
set diabetes(keep=id sex age);
length Group $ 8;
if age>=55 then group='Seniors';
else group='Under 55';
run;

You can use the LENGTH statement to create a variable and set the length of the variable. Here the LENGTH statement assigns a length to accommodate the longest value of the variable Group. The longest value is Under 55, which has eight characters. Because Group is a character variable, you must follow the variable name with a dollar sign ($).

For character variables, you must allow for the longest possible value in the first statement that uses the variable, because you cannot change the length with a subsequent LENGTH statement within the same DATA step. The maximum length of any character variable in the SAS System is 32,767 bytes. For numeric variables, you can change the length of the variable by using a subsequent LENGTH statement.

/*************************************/
/* create variable with FORMAT */
/*************************************/
data sales;
format Sale_Price 6.2;
Sale_Price=49.99;run;

/*************************************/
/* create variables with ATTRIB */
/*************************************/
data sales;
attrib Sale_Price format=6.2
label="Sale Price";
Sale_Price=49.99;
run;

Submit SAS programs to remote hosts (SAS/CONNECT)

options comamid=netbios remote=netpc;
The OPTIONS statement specifies the COMAMID= and the REMOTE= system options. These two system options define to the local session what type of link you want to establish to which remote host.
libname lhost 'c:\sales\reg1';
This LIBNAME statement defines a libref for the SAS library on the local session where the downloaded data set should be stored.
signon;
The SIGNON statement signs on to the remote host. You don't have to include a remote session ID when you have defined the REMOTE= system option in a previous OPTIONS statement.
rsubmit;
The RSUBMIT statement sends statements to the remote session for processing with the RSUBMIT statement. All statements are sent to the remote session until an ENDRSUBMIT statement is encountered.

Although you don't have to include a remote session ID, using a remote session ID in the RSUBMIT statement clarifies which remote session should process a group of statements when more than one link is active. If you omit the remote session ID, the RSUBMIT statement submits the statements to the remote session that is most recently identified in a SIGNON or an RSUBMIT statement or a REMOTE= system option.
libname rhost 'd:\dept12';

This LIBNAME statement defines the libref for the SAS library on the remote host.
proc download data=rhost.sales
out=lhost.sales;
run;
The PROC DOWNLOAD step transfers the data from the library on the remote host (RHOST) to the library on the local host (LHOST).
endrsubmit;
The ENDRSUBMIT statement signals the end of the block of statements that is to be submitted to the remote session. Statements following the ENDRSUBMIT statement are processed by the local session.

Read PC database files

To read PC database files, you use the IMPORT procedure. PROC IMPORT reads the input file and writes the data to a SAS data set, with the SAS variables defined based on the input records.

/*************************************/
/* import the Excel file */
/*************************************/
proc import datafile="c:\myfiles\Accounts.xls"
out=sasuser.accounts;
sheet="Prices";
getnames=no;
run;

/*************************************/
/* print part of the new data set */
/*************************************/
proc print data=sasuser.accounts(obs=10);
run;

/*************************************/
/* import the Access file */
/*************************************/
proc import table="customers"
out=sasuser.cust dbms=access;
uid="userid";
pwd="mypassword";
database="c:\myfiles\east.mdb";
wgdb="c:\winnt\system32\security.mdb";
run;
/*************************************/
/* print part of the new data set */
/*************************************/
proc print data=sasuser.cust(obs=5);
run;


/*************************************/
/* create variables with INPUT */
/*************************************/
data diabetes;
input ID $ Sex $ Age Height Weight
Pulse FastGlucose PostGlucose;
datalines;
2304 F 16 61 102 100 568 625
1128 M 43 71 218 76 156 208
4425 F 48 66 162 80 244 322
1387 F 57 64 142 70 177 206
9012 F 39 63 157 68 257 318
6312 M 52 72 240 77 362 413
;
run;

/*You can use keyword datalines; or cards; */

Read SAS data sets

data canada;
set mylib.productsales;
if country='CANADA';
run;

In this DATA step, each observation in the data set Mylib.ProductSales is read into the program data vector. Only those observations whose value of COUNTRY is CANADA are output to the new data set Canada.

data canada2;
set mylib.productsales;
if country='CANADA';
Total_Variance=actual-predict;
Forecast=actual*1.15;
run;

This DATA step creates data set Canada2 by reading data from data set Mylib.ProductSales and by calculating values for the two new variables Total_Variance and Forecast.

data product_sample;
do obsnum=1 to 100 by 2;
set mylib.productsales point=obsnum;
if _error_ then abort;
output;
end;
stop;
run;

These statements create the data set Product_Sample by selecting a subset of 50 observations from the data set Mylib.ProductSales, using the POINT= option to access observations directly by number.

Thursday, February 28, 2008

OBS, MEANS, UNIVARIATE, SORT

Only print 10 rows, but no observation line numbers
PROC PRINT DATA=auto(obs=10) noobs;
RUN;

We can get descriptive statistics separately for foreign and domestic cars (i.e., broken down by foreign) as shown below.
PROC MEANS DATA=auto;
CLASS foreign;
RUN;

We can get detailed descriptive statistics for price using proc univariate as shown below.
PROC UNIVARIATE DATA=auto;
VAR PRICE;
RUN;

When you use the noduplicates option, the SAS Log displays a note telling you how many duplicates were removed. As you see below, SAS informs us that 1 duplicate observation was deleted.
PROC SORT DATA=auto OUT=auto5 NODUPLICATES ;
BY DESCENDING foreign ;
RUN ;

It is common for duplicate observations to be next to each other in the same file, but if the duplicate observations are not next to each other, there is another strategy you can use to remove the duplicates. You can sort the data file by all of the variables (which can be indicated with the special keyword _ALL_), which would force the duplicate observations to be next to each other. This is illustrated below.
PROC SORT DATA=auto OUT=auto6 NODUPLICATES ;
BY _all_ ;
RUN ;

Reference Links

http://www.pt.ntu.edu.tw/hmchai/SAS/SAShome.htm
http://www.pt.ntu.edu.tw/hmchai/SAS/SASintroduction/Ex3heelpad.htm
http://www.csulb.edu/~msaintg/ppa696/696uni.htm
http://www.appstat.org.tw/
http://www.statedu.ntu.edu.tw/lecture/SAS_Bio_10/SAS_Bio_10.htm
http://www.uwsp.edu/psych/cw/statmanual/

http://www.ats.ucla.edu/stat/sas/default.htm
http://www.stat.unc.edu/students/owzar/stat101.html
http://its.unm.edu/introductions/Sas_tutorial/

SAS Language Reference: Dictionary
http://www.d.umn.edu/math/docs/saspdf/lgref/pdfidx.htm

http://gears.aset.psu.edu/hpc/education/tutorials/sas/sasstart/
http://www.theamericanprogrammer.com/programming/manuals.sas.shtml
http://www.asu.edu/sas/sasdoc/sashtml/proc/index.htm
http://www.asu.edu/sas/sasdoc/sashtml/proc/z0146802.htm
http://www.cpc.unc.edu/services/computer/presentations/sasclass99
http://learn.sdstate.edu/Dwight_Galster/510docs/Tutorial%20Programs/sas_tutorial_contents.htm
http://instruct.uwo.ca/sociology/300a/SASintro.htm
http://www.psych.yorku.ca/lab/sas/

USER Data Library

You can use one-level names for permanent SAS data sets by specifying a USER data library. You can assign a USER data library with a LIBNAME statement or with the SAS system option USER=. After you specify a USER data library, the procedure assumes that data sets with one-level names are in the USER data library instead of the WORK data library.

For example, the following PROC PRINT step assumes that DEBATE is in the USER data library:

options user='SAS-data-library';
proc print data=debate;
run;