data MaTable;
input Nom $ "A.D.C_EF"n $ Score_biomarqueur Score_pesticides "Q13t"n $ "Q13bist"n $ "Q1.A"n $ "Qt.2"n $;
datalines;
Doe John 30 1 oui o T i
Smith Jane 25 20 oui n T o
Brown Alice 35 2 non n T o
A C 2 2 non n K j
A C 5 23 non n K j
B John 10 21 non n K l
K C 31 13 oui o K l
B Jane 21 4 non o S l
;
run;
%macro stat_central();
proc sql ;
select name into :char_vars separated by ' '
from dictionary.columns where libname='WORK' and memname="MATABLE" and type='char';
quit;
%put &char_vars.;
%do k=1 %to %sysfunc(countw(&char_vars.));
%let char = %scan(&char_vars., &k.);
proc sort data=MATABLE;
by "&char."n;
run;
proc means data=MATABLE;
var Score_biomarqueur Score_pesticides;
class "&char."n;
run;
%end;
%mend;
%stat_central();
Hi,
Here is an extract from my table. I want to run this macro program but I get an error message because of the variables having dots. In fact, these variables separate into 2 or more variables. As a result, SAS no longer finds them in the base.
Can anyone help me solve this problem or suggest another approach?
Note that this is just an extract from the table. I have several variable names written with periods.
Best regards,
Gick
data MaTable;
input Nom $ "A.D.C_EF"n $ Score_biomarqueur Score_pesticides
"Q13t"n $ "Q13bist"n $ "Q1.A"n $ "Qt.2"n $;
datalines;
Doe John 30 1 oui o T i
Smith Jane 25 20 oui n T o
Brown Alice 35 2 non n T o
A C 2 2 non n K j
A C 5 23 non n K j
B John 10 21 non n K l
K C 31 13 oui o K l
B Jane 21 4 non o S l
;
run;
%macro stat_central();
proc sql;
select nliteral(name) into :char_vars separated by '|' from
dictionary.columns where libname='WORK' and memname="MATABLE" and
type='char';
quit;
%put &char_vars.;
%do k=1 %to %sysfunc(countw(&char_vars., |));
%let char = %scan(&char_vars., &k., |);
%put &char.;
proc sort data=MATABLE;
by &char.;
run;
proc means data=MATABLE;
class &char.;
var Score_biomarqueur Score_pesticides;
run;
%end;
%mend;
%stat_central();
Use NLITERAL to get the name in a valid naming format.
Use a delimiter that is not a space to delimit the list.
Add the delimiter specification to the COUNTW().
But you can also do this using CLASS and a WAYS statement without the loops and use _character_ to reference character variables.
proc means data=MATABLE;
class _character_;
ways 1;
var Score_biomarqueur Score_pesticides;
run;
You need to tell the macro to split words using the space character.
%do k=1 %to %sysfunc(countw(&char_vars.,%str( )));
%let char = %scan(&char_vars., &k.,%str( ));
Why a macro anyway? PROC MEANS/PROC SUMMARY can split the data by each class variable without macros, which also has the benefit of passing through the data only once, which might make a difference if you have very large data sets.
proc sql ;
select cats(quote(trim(name),"'"),'n') into :char_vars separated by ' '
from dictionary.columns where libname='WORK' and memname="MATABLE" and type='char';
quit;
%put &=char_vars;
proc means data=matable;
var Score_biomarqueur Score_pesticides;
class &char_vars;
ways 1;
run;
In general, I almost always avoid using dots and the like in variable names, if the database forces me to use dots or similar, I will usually rename the variables before I try to do other programming with them.
proc sql noprint;
select cats(quote(trim(name)),'n = ',quote(compress(trim(name),'.')),'n') into :renames separated by ' '
from dictionary.columns where libname='WORK' and memname="MATABLE" and type='char';
quit;
%put &=renames;
proc datasets library=work nolist;
modify matable;
rename &renames;
run; quit;
@Gick wrote:
However the code returns the results to me several times. In fact, as many variables, as many results are repeated.
I don't know what this means. Show us the code. Show us the output.
Most simple solution: don't allow these stupid name literals in the first place. Funny strings belong in labels.
data MaTable;
input Nom $ "A.D.C_EF"n $ Score_biomarqueur Score_pesticides
"Q13t"n $ "Q13bist"n $ "Q1.A"n $ "Qt.2"n $;
datalines;
Doe John 30 1 oui o T i
Smith Jane 25 20 oui n T o
Brown Alice 35 2 non n T o
A C 2 2 non n K j
A C 5 23 non n K j
B John 10 21 non n K l
K C 31 13 oui o K l
B Jane 21 4 non o S l
;
run;
%macro stat_central();
proc sql;
select nliteral(name) into :char_vars separated by '|' from
dictionary.columns where libname='WORK' and memname="MATABLE" and
type='char';
quit;
%put &char_vars.;
%do k=1 %to %sysfunc(countw(&char_vars., |));
%let char = %scan(&char_vars., &k., |);
%put &char.;
proc sort data=MATABLE;
by &char.;
run;
proc means data=MATABLE;
class &char.;
var Score_biomarqueur Score_pesticides;
run;
%end;
%mend;
%stat_central();
Use NLITERAL to get the name in a valid naming format.
Use a delimiter that is not a space to delimit the list.
Add the delimiter specification to the COUNTW().
But you can also do this using CLASS and a WAYS statement without the loops and use _character_ to reference character variables.
proc means data=MATABLE;
class _character_;
ways 1;
var Score_biomarqueur Score_pesticides;
run;
And you don't need to re-count the number of names.
PROC SQL already counted them for you. so just remember that number.
proc sql;
select nliteral(name)
into :char_vars separated by '|'
from dictionary.columns
where libname='WORK'
and memname="MATABLE"
and type='char'
;
%let nvars=&sqlobs;
quit;
%do i=1 %to &nvars;
...
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.