Sometimes labels for variables get "dropped" during data preparation and cleaning. One example is when data are transposed from "wide form" to "long form." For example, suppose a data set has three variables, X, Y, and Z, each with labels. If you transpose the data to long form, the new data set contains two variables VARNAME (with values "X", "Y", and "Z") and VALUE (which contains the data values). After the transpose operation, the labels of the former variables might not be available to additional procedures that analyze the data.
However, you can easily look up a label. This article shows how to look up a variable's label and copy it into a macro variable so that it can be used in reports and graphs. I recently used this technique to display a variable's label on the axis of a graph.
A simple way to get a variable's attributes
Did you know that there are DATA step functions in SAS that get the attributes of variables?
- VFORMAT function: Get the name of the format that is associated with a variable.
- VINFORMAT function: Get the name of the informat that is associated with a variable.
- VLABEL function: Get the label of a variable.
- VLENGTH function: Get the length of a variable. This is most useful for character variables.
- VNAME function: Get the name of a variable as a string. This is most useful when working with arrays of variables.
- VTYPE function: Get the type of a variable. A numeric variable has type 'N', whereas a character variable has type 'C'.
- VVALUE function: Get the value of a variable.
For example, the following DATA step uses the VLABEL function, followed by a call to the SYMPUT subroutine to copy the value into a macro variable.
%let DSName = Sashelp.Iris; /* data set name */ %let Var = SepalLength; /* response variable */ /* look up the label of the variable; create a macro variable */ data _null_; set &DSName(obs=1); /* load attributes of variables */ label = vlabel(&Var); /* get the variable's label */ call symput("Labl", label); run; %put &=Labl; |
LABL=Sepal Length (mm) |
The call to the VLABEL is straightforward. My implementation reads one observation from the input data. There is, in fact, a sneaky way to load the attributes without reading ANY observations, but it is somewhat esoteric. For the interested reader, I direct you to the common SAS trick for getting the number of observations into a macro variable, which uses an "IF 0 THEN SET" clause to set the variable attributes and uses a STOP statement to handle the fact that the DATA step does not encounter an end-of-file token. See the link for details.
But what about dictionaries?
The previous DATA step is short and easy to understand, but I can hear some of my readers exclaim, "But wait! What about DICTIONARY tables?"
Experienced SAS programmers might use DICTIONARY tables for this task. You can get metadata about variables (formats, lengths, labels, etc.) by using PROC SQL to examine the Dictionary.columns table, or by using the DATA step and the Sashelp.vcolumn table. DICTIONARY tables are powerful resources, but the VLABEL function is much simpler in this instance. For a comparison, I include an Appendix that demonstrates how to use dictionaries.
Summary
You can use the VLABEL function in a SAS DATA step to get the label for a variable. Similar functions exist to get other variable attributes, such as formats (VFORMAT), type (VTYPE), and name (VNAME). These functions provide a simple way to get a variable's metadata. An example that uses DICTIONARY tables is shown in the Appendix.
Appendix: Using DICTIONARY tables to get the label of a variable
If you have ever been to a SAS conference, you know that DICTIONARY tables are a favorite topic for SAS programmers. DICTIONARY tables are read-only tables that provide information about the state of the SAS session, including libraries, data sets, variables, and system options.
For completeness, here is some DATA step code that gets the label for a variable. The first DATA step extracts the libref and the data set name from a two-level specification of the data set. In some situations, you can skip this step.
%let DSName = Sashelp.Iris; /* two-level data set name */ %let Var = SepalLength; /* response variable */ /* if necessary, extract libname and member name from two-level name */ data _null_; k = find("&DSName", "."); /* find the position of the dot */ if k > 0 then lib = upcase(substr("&DSName", 1, k-1)); /* if two-level name */ else lib = "WORK"; /* if one-level name */ mem = upcase(substr("&DSName", k+1)); call symput("Lib", lib); /* LIB contains the libref */ call symput("Mem", mem); /* MEM contains the data set name */ run; |
The result of the previous DATA step is to parse a two-level data set name and create two macro variables: LIB contains the libref and MEM contains the name of the data set. You can use these values to access the DICTIONARY table that contains information about columns. Here is the DATA step approach:
/* look up the label of the original variable; create macro variable */ data _null_; set Sashelp.vcolumn(where=( libname="&Lib" and memname="&Mem" & upcase(name)=upcase("&Var"))); call symput("Labl", label); put label; run; %put &=Labl; |
If you prefer, you can also use the PROC SQL to obtain this information:
/* Alternative: use PROC SQL and the DICTIONARY tables */ proc sql ; select label into :Labl from dictionary.columns where libname="&Lib" AND memname="&Mem" AND upcase(name)=upcase("&Var"); quit; %put &=Labl; |
4 Comments
Rick,
Corresponding to VLABEL() VNAME() VFORMAT() ,there are another set of functions VARLABEL() VARNAME() VARFORMAT() to get variable label.
%let DSName = Sashelp.Iris; /* data set name */
%let Var = SepalLength; /* response variable */
%let dsid=%sysfunc(open(&dsname.));
%let vlabel=%sysfunc(varlabel(&dsid.,%sysfunc(varnum(&dsid.,&var.))));
%let dsid=%sysfunc(close(&dsid.));
%put NOTE:&=vlabel.;
Yes. The functions you mention are related to files. They more limited than the functions I used.
Great, I think proc contents could be used oftenly, too.
Yes. Instead of using a DICTIONARY table, you could write code such as this: