macro SAS9

Debugging a Macro for Frequency Tables

Simon 20/05/2021 3 vistas

Automating repetitive tasks is one of SAS©'s great strengths, especially for processing large-scale surveys. However, passing parameters—such as labels or formats—inside a macro is a frequent source of syntax errors.

Note :
The Need: Automate PROC FREQ with Metadata
The user wants to create a %f_freq macro to generate frequency tables. The requirements are specific:

The output must be a data table (OUT=).

The variable must be formatted (grouping of values).

A specific (often long) label must be assigned to the variable in the output table, defined beforehand via a %LET statement.

The problematic code:
1%let Q1_label='Texte très long pour la question 1...';
2 
3%macro f_freq(var, var_w, var_label);
4 PROC FREQ DATA=clean_data order=freq;
5 TABLE &var / out=freqout.freq_&var;
6 FORMAT &var &var_w;
7 label &var=&var_label; /* Assigne le label */
8 RUN;
9%mend;
10 
11/* L'appel qui ne fonctionne pas comme prévu */
12%f_freq(Q1, Q1_w., Q1_label);
Note :
The Error: Macro Variable Resolution (&)
As pointed out in the forum response, the error is not in the macro definition, but in its call.

The user wrote: %f_freq(Q1, Q1_w., Q1_label);

The problem: SAS© literally interprets the third parameter as the text "Q1_label". Consequence: In the procedure, SAS© tries to execute label Q1 = Q1_label;, which assigns the text "Q1_label" as the label, instead of the text contained in the variable (the "Very long text...").

The solution: You must use the & (ampersand) sign to tell SAS© to resolve the variable before sending it to the macro.
1/* Appel corrigé */
2%f_freq(Q1, Q1_w., &Q1_label);
3 

The Impact of Formats and Labels on PROC FREQ

The expert who responded raises an interesting technical point: "I think the format and the label are used for display... I don't think they affect the aggregation."

It is important to clarify this behavior in SAS©:

  1. Formats (FORMAT): They do affect aggregation. If you apply a format that groups values (for example, transforming 1, 2, 3 into "Small"), PROC FREQ will calculate the frequency for "Small". This is essential for on-the-fly recoding.

  2. Labels (LABEL): They do not affect the calculation, but they are crucial for metadata. The LABEL statement inside the procedure does indeed allow storing the variable's description in the output table (OUT=).

Note :
Debugging Best Practices
To avoid this kind of confusion between a variable's name and its content, here are two tips from the discussion:

Use %PUT: Before running a complex procedure, display the values in the Log to check what the macro is actually receiving.
1%macro f_freq(var, var_w, var_label);
2 %put NOTE: La variable est &var;
3 %put NOTE: Le label reçu est &var_label;
4 /* ... reste du code ... */
5%mend;
Beware of Quotes: If your label already contains quotation marks (as defined in %let Q1_label='...'), make sure not to add extra ones in the label &var=&var_label; statement.

Writing macros requires particular rigor regarding variable scope. Always remember: if you want to pass the content of a variable defined by a %LET statement, you must use the & prefix in the call.

Referencias y Documentos