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?
10, because LENGTH always overrides an assignment statement
Compilation fails with a conflicting-attributes error
10, because LENGTH statements are hoisted to the top of the step
1, because compilation fixes the length at the first reference and the later LENGTH statement is too late
Which statement is true about a LABEL statement coded inside a DATA step versus inside a PROC PRINT step?
Both are temporary and vanish when the step ends
Labels can be assigned only in PROC steps
The PROC step label is permanent; the DATA step label is temporary
The DATA step label is stored permanently in the descriptor portion; the PROC step label applies only to that procedure
Consider data work.out; set work.in(rename=(Qty=Quantity)); if Qty > 100; run;. What happens?
The step runs correctly, because SAS resolves Qty to Quantity automatically
SAS issues an error stating that variable Qty is not on file WORK.IN, because the input RENAME= takes effect as the variable enters the PDV
The step runs but Quantity is set to missing for every row
SAS renames the variable only on output, so Qty remains valid in the subsetting IF
A report must show the raw stored value of a variable that carries a permanent DATE9. format. Which approach works?
Add the UNFORMATTED option to the PROC PRINT statement
Code format TxnDate; naming the variable with no format after it, which clears the format association
Code informat TxnDate; to override the display
Assign TxnDate = input(TxnDate, 8.); to strip the format
Sections you finish are checked off in the contents.