4.2 Modifying Variable Attributes with LENGTH, LABEL, FORMAT & RENAME=
Key Takeaways
- LENGTH is a compile-time statement and must appear before the variable's first reference; placed afterwards it cannot change the already-fixed length.
- LABEL and FORMAT statements inside a DATA step attach permanent attributes stored in the descriptor portion, while the same statements inside a PROC step apply only for that step.
- Numeric variables occupy 8 bytes by default and may be shortened to as few as 3 bytes, but shortening a numeric that holds large integers silently destroys precision.
- RENAME= as an input data set option renames the variable as it enters the PDV, so all later statements must use the new name; the RENAME statement renames only on output.
- ATTRIB sets length, label, format, and informat for a variable in a single statement and follows the same compile-time placement rule as LENGTH.
4.2 Modifying Variable Attributes with LENGTH, LABEL, FORMAT & RENAME=
Quick Answer: The A00-231 content guide lists "Modify variable attributes using options and statements in the DATA step" as a main objective and names three tools explicitly: the
RENAME=data set option, theLABELandFORMATstatements, and theLENGTHstatement. All of them are compile-time constructs — where you put them in the DATA step decides whether they work at all.
Every SAS variable carries six attributes: name, type (numeric or character), length in bytes, format, informat, and label. Type is immutable once compiled. The other five can be set or changed, and the exam repeatedly tests which statement changes which attribute and where it must be placed.
1. LENGTH: Reserving Bytes Before the First Reference
LENGTH variable-1 <$> length-1 variable-2 <$> length-2 ... ;
The $ marks a character variable; without it SAS creates a numeric.
data work.orders_typed;
length Status $ 13 Region $ 2 OrderID 8;
set work.orders_raw;
if Amount < 50 then Status = 'Low';
else if Amount < 200 then Status = 'Medium';
else Status = 'High Priority';
run;
The rule that matters: LENGTH executes during compilation, and compilation reads the step top to bottom. A variable's length is fixed by whichever construct mentions it first. Move that LENGTH statement below the IF block and Status becomes 3 bytes — the width of 'Low' — silently truncating every longer value.
Character versus Numeric Lengths
| Type | Default length | Legal range | Consequence of shortening |
|---|---|---|---|
| Character | Width of the first value assigned | 1 to 32,767 | Values longer than the length are truncated on the right, silently |
| Numeric | 8 bytes | 3 to 8 (Windows/UNIX) | Fewer bytes means fewer mantissa bits: integer precision degrades |
data work.precision_trap;
length SmallCode 3; /* 3-byte numeric */
SmallCode = 8388609; /* beyond 3-byte integer precision */
FullCode = 8388609; /* default 8 bytes - exact */
run;
Exam Trap: shortening a numeric variable saves disk but is safe only for small integers such as flags and short codes. A 3-byte numeric stores integers exactly only up to 8,192 and a 4-byte numeric only to 2,097,152. Never shorten a numeric that holds an identifier, a currency amount, or a SAS datetime value.
2. LABEL: Descriptive Column Headings
LABEL variable-1 = 'descriptive text' variable-2 = 'descriptive text';
A label is descriptive text of up to 256 characters that reporting procedures can print instead of the variable name.
/* Permanent: stored in the descriptor portion of WORK.SALES_LABELED */
data work.sales_labeled;
set work.sales;
label GrossAmt = 'Gross Sales Amount (USD)'
RegCode = 'Sales Region Code';
run;
/* Temporary: applies to this PROC PRINT only */
proc print data=work.sales label;
label GrossAmt = 'Gross Sales Amount (USD)';
run;
| Where the LABEL statement appears | Persistence |
|---|---|
| Inside a DATA step | Permanent — written into the descriptor portion and reused by every later step |
| Inside a PROC step | Temporary — applies only to that procedure invocation |
Exam Trap: a label in a
PROC PRINTstep does nothing unless theLABEL(orSPLIT=) option appears on thePROC PRINTstatement.PROC MEANS,PROC FREQ, andPROC REPORTdisplay labels by default, so the trap is specific toPROC PRINT.
3. FORMAT and INFORMAT: Display and Reading Instructions
A format controls how a stored value is displayed; an informat controls how raw text is read in. Neither changes the stored value.
data work.formatted;
set work.transactions;
format TxnDate date9.
Amount dollar12.2
Rate percent8.1;
run;
/* Removing a format: name the variable with no format after it */
data work.unformatted;
set work.formatted;
format TxnDate; /* TxnDate now prints as the raw day count */
run;
That last idiom is worth memorizing. format Variable; with nothing after the variable name clears the format. It is the correct answer whenever a question asks how to see raw stored values, because PROC PRINT has no UNFORMATTED option.
4. ATTRIB: All Attributes in One Statement
data work.attrib_demo;
attrib Amount length=8 format=dollar12.2 label='Gross Amount'
Status length=$13 label='Order Status'
TxnDate length=8 format=date9. informat=mmddyy10.
label='Transaction Date';
set work.orders_raw;
run;
ATTRIB obeys the same compile-time placement rule as LENGTH: it must precede the variable's first reference to control its length.
5. RENAME Statement versus RENAME= Data Set Option
This distinction is a reliable exam item because the two constructs look similar and behave differently.
| Construct | When the rename happens | Which name later statements must use |
|---|---|---|
RENAME statement (rename Old=New;) | When the PDV is written to output | The old name, throughout the step |
RENAME= on an input data set (set ds(rename=(Old=New))) | As the variable enters the PDV | The new name, from that point on |
RENAME= on an output data set (data out(rename=(Old=New))) | When the row is written out | The old name, throughout the step |
/* Input option: subsequent logic MUST use the new name */
data work.renamed_in;
set sashelp.class(rename=(Age=YearsOld));
if YearsOld > 13; /* correct - Age no longer exists */
run;
/* RENAME statement: logic uses the OLD name */
data work.renamed_out;
set sashelp.class;
if Age > 13; /* correct - rename happens on output */
rename Age = YearsOld;
run;
Referring to Age after an input-side RENAME= produces ERROR: Variable Age is not on file; referring to YearsOld before a RENAME statement produces an uninitialized-variable note and a column of missing values.
6. Attribute Precedence Summary
| Attribute | Set with | Placement rule |
|---|---|---|
| Length | LENGTH, ATTRIB | Before the first reference |
| Label | LABEL, ATTRIB | Anywhere in the step |
| Format | FORMAT, ATTRIB | Anywhere in the step |
| Informat | INFORMAT, ATTRIB | Before the INPUT statement that uses it |
| Name | RENAME statement or RENAME= option | Depends on the input versus output side |
| Type | — | Cannot be changed; create a new variable instead |
A DATA step assigns Grade = 'A'; and, three statements later, contains length Grade $ 10;. What length does Grade have in the output data set?
Which statement is true about a LABEL statement coded inside a DATA step versus inside a PROC PRINT step?
Consider data work.out; set work.in(rename=(Qty=Quantity)); if Qty > 100; run;. What happens?
A report must show the raw stored value of a variable that carries a permanent DATE9. format. Which approach works?