I am using SAS Enterprise Guide 8.3
I created a varlist and I need to add quotes around each member of the list.
From: %let varlist = 0001 0002 0003 ... 99999;
to: %let newvarlist= '0001' '0002' '0003' ... '99999';
My goal is to do something similar to the following. PD is a character variable.
data new;
set old;
if pd in (%varlist) then newvar=1;
else newvar=0;
run;
I have tried a few solutions posted on the community and I keep getting error messages.
Method 1:
data new;
set old;
if index(" &varlist", ' ' || strip(var1) || ' ') then do;
newvar=1;
end;
run;
Warning message: Apparent invocation of &varlist not resolved.
The Frequency table of newvar has all obs missing.
Method 2
%let varlist=aaaaa bbbbb ccccc zzzzz;
%let varlist_quotes=%nrbquote(')%qsysfunc(prxchange(s/\s+/%nrbquote(' ')/oi,-1,&varlist))%nrbquote(');
%put varlist_quotes: %bquote(&varlist_quotes);
Error message:
Closing delimiter"/" not found after replacement text "s/\s' ' oi".
The regular expression passed to the function PRXCHANGE contains a syntax error.
Any help provided would be appreciated.
Try the %qlist macro from https://github.com/sasutils/macros/blob/master/qlist.sas
And then you don't have to write your own code
filename qlist url 'https://raw.githubusercontent.com/sasutils/macros/master/qlist.sas';
%include qlist;
%let varlist = 0001 0002 0003 99999;
%let my_list= %qlist(&varlist., paren=0, comma=0, delimit=, dsd = 0, quote=1);
%put &my_list.;
Hi @ajb ,
One way to do is creating macro variable using PROC SQL into clause. See the example below:
data have;
length varlist $ 12;
input varlist;
cards;
0001
0002
0003
99999
;
proc print;run;
proc sql;
select distinct compress(quote(varlist))
into: varlist separated by ','
from have;
%put &=varlist;
quit;
The result, all id values put in macro variable with proper quotations.
Testing:
data test;
set have;
if varlist in (&varlist) then flag=1;
else flag=0;
proc print;run;
Good idea, but don't add the COMPRESS() function unless your intent is to create a macro variable with values that are DIFFERENT from the values in the source dataset.
But since SAS ignores trailing spaces in string comparisons you could use TRIM() to make the generated variable shorter. Also depending on the values and where you use the macro variable you might want to use single quotes around the strings to prevent the macro processor from trying to process any & or % characters that might be in the strings.
proc sql noprint;
select distinct quote(trim(variable),"'")
into :varlist separated by ','
from have
;
quit;
%put &=sqlobs &=varlist;
How did you create that list in the first place? If not manually, the quote function makes it easy to add quotes when creating macro variables.
proc sql noprint;
select quote(name, "'") into :name_list separated by " "
from sashelp.class;
quit;
%put &name_list.;
%let varlist = 0001 0002 0003 99999; %let newvarlist= %sysfunc(prxchange(s/(\w+)/'\1'/,-1,&varlist.)); %put &=newvarlist;
Hi @ajb
Another solution. Note that &varlist gets a leading and trailing quote before the tranwrd function is applied. I works anyway, but gives annoying warning notes if done outside tranwrd.
%let varlist = aaaaa bbbbb ccccc zzzzz;
%let newvarlist= %sysfunc(tranwrd(%str(%')&varlist%str(%'),%str( ),%str(' ')))%str(%');
%put &=newvarlist;
23 %let varlist = aaaaa bbbbb ccccc zzzzz; 24 %let newvarlist= %sysfunc(tranwrd(%str(%')&varlist%str(%'),%str( ),%str(' '))); 25 %put &=newvarlist; NEWVARLIST='aaaaa' 'bbbbb' 'ccccc' 'zzzzz'
I typically would do this
%Let varlist = 0001 0002 0003 ... 99999;
%let newvarlist = %str(%')%qsysfunc(tranwrd(&varlist, %str( ), %str(%',%') ) )%str(%');
data new;
set old;
if pd in (%unquote(&newvarlist)) then newvar=1; /* The %unquote() is needed to avoid errors */
else newvar=0;
run;
Hope this helps
You could use zipEvalf macro from the BasePlus package.
Here are the steps:
1) install SAS Packages Framework and the BasePlus Package:
filename packages "%sysfunc(pathname(work))"; /* setup WORK as temporary directory for packages (you can change it to permanent directory) */
filename SPFinit url "https://raw.githubusercontent.com/yabwon/SAS_PACKAGES/main/SPF/SPFinit.sas";
%include SPFinit;
%installPackage(SPFinit) /* install SAS Packages Framework */
%installPackage(basePlus) /* install basePlus package */
2) read help for the zipEvalf macro and load the macro into the session:
%helpPackage(basePlus, zipEvalf) /* get help about the zipEvalf macro from the basePlus package */
%loadPackage(basePlus, cherryPick=zipEvalf) /* load the zipEvalf macro of the basePlus package content into the SAS session */
3) Run the code:
%let varlist = 0001 0002 0003 ... 99999;
%put Before: &=varlist;
%let varlist = %zipEvalf(&varlist., %str(%'), function=Quote);
%put After: &=varlist;
Log:
1 %let varlist = 0001 0002 0003 ... 99999; 2 %put Before: &=varlist; Before: VARLIST=0001 0002 0003 ... 99999 3 %let varlist = %zipEvalf(&varlist., %str(%'), function=Quote); 4 %put After: &=varlist; After: VARLIST='0001' '0002' '0003' '...' '99999'
Links:
a) SAS Packages Framework: https://github.com/yabwon/SAS_PACKAGES
b) BasePlus packages: https://github.com/SASPAC/baseplus
Bart
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.