SAS using macro in a title - sas

What is the purpose of title Title "&TitleX" here?
Is there any difference between doing the first and second way?
%let TitleX=PROC PRINT Of Only &Cyl_Count Cylinder Vehicles; %let Cyl_Count=5;
Title "&TitleX";
proc print data=sashelp.cars;
where Cylinders=&Cyl_Count;
var Type Make Model Cylinders MSRP; run;
title PROC PRINT Of Only &Cyl_Count Cylinder Vehicles; %let Cyl_Count=5;
proc print data=sashelp.cars;
where Cylinders=&Cyl_Count;
var Type Make Model Cylinders MSRP; run;

There are two differences. One is that the macro variable exists and can be used for something else if you want. The second is how the TITLE statement is generated. The version that is using the TITLEX macro variables is using quotes and the other is not, but that really doesn't have anything to do with the macro variable.

Related

SAS: How do I rename an axis label name on sgplot scatter plot

I'm an Animal science student from Slovenia and I'm just finishing my master's thesis. For the finishing touches i need to make a bunch of scatter plots of different traits. All my data values (breeding values of different traits) are in code, for example m_pv10 (omišičenost = muscularity), m_pv31 (age of first calving),... To make the scatter plots easier to read i'd like to rename the x and y-axis labels from m_pv31 to "Age of first calving". I have tried renaming the values in a data step to bypass this problem but some names of the traits include spaces "age of first calving" and no nregular letters as "š" and "č" so the data step won't work.
data datam_copy;
set datam_copy;
rename m_pv10=Omišičenost;
m_pv31=Starost ob prvi telitvi;
m_pv12=Vime;run;
Is there a way to rename the axis labels directly in the sgplot code?
I would be very tratefull for any suggestions.
Urban
You can use the variable label, if that is the level you're working at. Here's an example.
data have;
set sashelp.class;
label age="Age of student"
height="Height of student"
weight="Weight of student"
;
run;
proc sgplot data=have;
vline age/response=height;
vline age/response=weight y2axis;
run;
You can rename the variable also of course, but this is really the job of the variable label. You can also use the label statement directly in sgplot.
proc sgplot data=sashelp.class;
vline age/response=height;
vline age/response=weight y2axis;
label age="Age of student"
height="Height of student"
weight="Weight of student"
;
run;
You can have spaces in the name but generally not a great idea though.
Not sure how the accents will work though.
options validvarname = any;
data datam_copy;
set datam_copy;
rename m_pv10= 'Omišičenost'n;
m_pv31= 'Starost ob prvi telitvi'n;
m_pv12= 'Vime'n;
run;

loop a list of variables in SAS

I have a dataset with 10+ dependent variables and several categorical variables as independent variables. I'm plan to use proc sgplot and proc mixed functions to do analysis. However, putting all variables one by one in the same function will be really time consuming. I'm pretty new to SAS, is there a way to create a loop with dependent variables and put them into the function.
Something like:
%let var_list= read math science english spanish
proc mixed data=mydata;
model var_list= gender age race/ solution;
random int/subject=School;
run;
Thank you!
SAS has a macro language you can use to generate code. But for this problem you might want to just restructure your data so that you can use BY processing instead.
data tall ;
set mydata ;
array var_list read math science english spanish ;
length varname $32 value 8;
do _n_=1 to dim(var_list);
varname=vname(var_list(_n_));
value = var_list(_n_);
output;
end;
run;
proc sort data=tall;
by varname ;
run;
Now you can process each value of VARNAME (ie 'read','math', ....) as separate analyses with one PROC MIXED call.
proc mixed data=tall;
by varname;
model value = gender age race/ solution;
random int/subject=School;
run;
I would do something like this. This creates a loop around your proc mixed -call. I didn't take a look at the proc mixed -specification, but that may not work as described in your example.
The loop works however, and loops through whatever you put in the place of the proc mixed -call and the loop is dynamically sized based on the number of elements in the dependent variable list.
First define some macro variables.
%let y_var_list = read math science english spanish;
%let x_var_list = gender age race;
%let mydata = my_student_data;
Then define the macro that does the looping.
%macro do_analysis(my_data=, y_variables=, x_variables=);
%* this checks the nr of variables in y_var_list;
%let len_var_list = %eval(%sysfunc(count(&y_variables., %quote( )))+1);
%do _i=1 %to &len_var_list;
%let y_var = %scan(&y_variables, &_i);
%put &y_var; %* just printing out the macrovar to be sure it works;
%* model specification;
proc mixed data=&my_data.; %* data given as parameter in the macro call. proc mixed probably needs some output options too, to work;
model &y_var = &x_variables/ solution; %* independent vars as a macro parameter;
random int/subject=School;
run;
%end;
%mend do_analysis;
Last but not least, remember to call your macro with the given variable lists and dataset specifications. Hope this helps!
%do_analysis(my_data=&mydata, y_variables=&y_var_list, x_variables=&x_var_list);

How can I peform same datastep across many variables in SAS?

I have data that looks like this and has 500 variables with a target:
var1 var2 var3 var4 ... var500 target
The names of the variables are not sequential as above so I don't think I can use something like var1:var500. I want to loop through the variables to create graphs. Some of the variables are continous and some are nominal.
for var1 through var500
if nominal then create graphtypeA var[i] * target
else if continous then create graphtypeB var[i] * target
end;
I can easily create a second table that has the data type in it to check against. Arrays seem like they might be useful to peform this task of looping through variables. Something like:
data work.mydata;
set archive.mydata;
array myarray{501] myarray1 - myarray501
do i=1 to 500;
proc sgpanel;
panelby myarray[501];
histogram myarray[i];
end;
run;
This doesn't work though and it doens't check to see what type of variable it is. If we assume I have another sas.dataset that has varname and vartype (continuous, nominal) how can I loop through to create the desired graphs for the given vartype? Thanks in advance.
Basically, you need to loop over some variables, apply some logic to determine the variable type, then produce output depending on the variable type. While there are many approaches to this problem, one solution is to select your variables into a macro variable, loop over this "list" (not a formal data structure) of variables, and use macro control logic to designate different subroutines for numeric and character variables.
I'll use the sashelp.cars data set to illustrate. In this example the variable origin is your 'Target' variable and the variables Make, Type, Horsepower, and Cylinders are the numeric and character variables.
* get some data;
data set1 (keep = Make Type Origin Horsepower Cylinders);
set sashelp.cars;
run;
* create dataset of variable names and types;
proc contents data = set1
out = vars
noprint;
run;
* get variable names and variable types (1=numeric, 2=character)
* into two macro variable "lists" where each entry is seperated
* by a space;
proc sql noprint;
select name, type
into :varname separated by ' ', :vartype separated by ' '
from vars
where name <> "Make";
quit;
* put the macro variables to the log to confirm they are what
* you expect
%put &varname;
%put &vartype;
Now, use a macro to loop over the values in the macro variable list. The countw function counts the number of variables, and uses this number as the loop iterator limit. The scan function reads in each variable name and type by its relative position in the respective macro variable lists. For each variable the type is then evaluated and a plot is produced depending on whether it is character or numeric. In this example, a histogram with density plot is produced for numeric variables and a bar chart of frequency counts is produced for character variables.
The loop logic is general, and Proc sgpanel and Proc sgplot cab be modified or replaced with other desired data step processing or procedures.
* turn on options that are useful for
* macro debugging, turn them off
* when using in production;
options mlogic mprint symbolgen;
%macro plotter;
%do i = 1 %to %sysfunc(countw(&varname));
%let nextvar = %scan(&varname, &i, %str( ));
%let nextvartype = %scan(&vartype, &i, %str( ));
%if &nextvartype. = 1 %then %do;
proc sgpanel data=set1 noautolegend;
title "&nextvar. Distribution";
panelby Origin;
histogram &nextvar.;
density &nextvar.;
run;
%end;
%if &nextvartype. = 2 %then %do;
proc sgplot data=set1;
title "&nextvar. Count by Origin";
vbar &nextvar. /group= origin;
run;
%end;
%end;
%mend plotter;
*call the macro;
%plotter;
Unfortunately it is not possible to use arrays outside a data step in the way that you propose here, at least not in any very efficient way. However, there are quite a few options available to you. One would be just to call your graphing proc once and tell it to graph every numeric variable in your dataset, e.g. like so:
proc univariate data = sashelp.class;
var _NUMERIC_;
histogram;
run;
If the variables you want to graph that are of the same type are adjacent in the column order of your dataset, you can use a double-dash list, e.g.
proc univariate data = sashelp.class;
var age--weight;
histogram;
run;
In general you should seek to avoid calling procs or running data steps separately for every variable - it is nearly always more efficient to call them just once and process everything in one go.

Add Title To SAS Output Graphs

I'm using template and sgrender in SAS to create heatmaps based on a different class variable. I'd like the output to update the title based off of the class variable each time to what the value of the class variable. So far, my code is like this (it prints a string title if I tell it to, but i can't get it to vary depending on the variable):
proc template;
define statgraph heatmapparm;
begingraph;
entrytitle 'INSERT TITLE HERE'; *Update title here based on classVar;
layout overlay;
heatmapparm x=magX2 y=magZ2 colorresponse=percent / colormodel=(blue yellow red)
name="heatmapparm" xbinaxis=false ybinaxis=false datatransparency=0;
continuouslegend "heatmapparm" / location=outside valign=bottom;
endlayout;
endgraph;
end;
run;
title #byval(classVar);
proc sgrender data=dataSet template=heatmapparm;
by classVar;
run;
Thank you all!
Use Macro variables to alter the titles. Here is an example
%let classVar=VARIABLEVALUE1;
title &classVar.;
proc sgrender data=dataSet template=heatmapparm;
by &classVar.;
run;
You can always write cleaner code by putting the proc sgrender code inside a SAS MACRO.

macro to transpose and add a prefix after ordering columns' names

I need to run a macro that does a transpose for many variables (and creates a table for each one), orders the columns names, which are numeric, but also adds as a prefix the variable's name (which is a string).
I have a macro in SAS to perform a transpose with different variables as var in the transpose. The code is:
%macro transponer(var);
proc transpose data=labo2.A_svm_200711_200806
out=labo2.D_tr_&var.0;
var &var;
id mes;
by cid;
run;
/*......more code.....*/
select cats(name, '=', &var, name)
into :prefijolista
separated by ' '
from dictionary.columns
where libname='LABO2' and memname= cats('D_TR_',upcase(&var))
and name like '_20%';
quit;
%put &prefijolista;
%mend;
Since mes is numeric I wanted to order the variable, that's why I didn't introduce the "prefix &var" in the proc transpose but instead I did it after the retain (that was useful to order the columns).
The problem starts when I try to introduce the prefix (after the ordering).
Since one of the variables' name is for example "monto", I get the following error (because it is the var variable in the transpose and it's not a column name in the transposed table):
The following columns were not found in the contributing tables:
monto.
My next step would be:
proc datasets library=labo2;
modify D_tr_&var.0;
rename &prefijolista;
quit;
But I cant do it untill I get the previous one done.
So I don't know how to order the columns after the transpose and also add the prefix.
How can I solve this?
Thanks!
You need to rename the columns using something like PROC DATASETS.
proc datasets lib=work nolist;
modify myDataSet;
rename old_col_name = new_col_name;
run;
quit;
A documentation example is available in the Base SAS guide under the doc for PROC DATASETS. It is available online at: http://support.sas.com/documentation/cdl/en/proc/67327/HTML/default/viewer.htm#n0mfav25learpan1lerk79jsp30n.htm
The problem was that &var inside the cats function inside a macro hast to use
" "
Also you could use
sysfunc(cats(D_TR, &a)
So finally the code will remain like:
%let a = %upcase(&var);
%put &a;
%let b=%sysfunc(cats(D_TR_,&a));
%put &b;
proc sql;
select cats(name, '=', "&var" , name)
into :prefijolista
separated by ' '
from dictionary.columns
where libname='LABO2' and memname= "&b"
and name like '_20%';
quit;
%put &prefijolista;
%put "&b";
PROC datasets library=LABO2;
modify &b;
rename &prefijolista;
quit;
%put "ult" &b;
Not very straightforward, but worked. :)