Hi,
I wrote a simple macro for Proc Phreg function below.
I would like to export the HR (95% C.I.) for all variables in one Excel file. Could anyone please help me with the code? Thank you all in advance.
%macro HR(x=);
proc phreg data = CP1;
class &x;
model Time*Event(0) = &x /rl;
run;
%mend HR;
%HR(x=Gender);
%HR(x=Disease_Type);
%HR(x=Disease_Status);
%HR(x=Active_Therapy);
Hi,
I see, try this:
libname out xlsx "C:\want.xlsx"; %macro HR(x=); %let outputName=_PE%substr(%cmpres(&x.),1,%sysfunc(min(%length(&x.),29))); ods graphics off; ods output ParameterEstimates=&outputName.; proc phreg data = CP1; class &x; model Time*Event(0) = &x /rl; run; ods output close; ods graphics on; %mend HR; %HR(x=Gender); %HR(x=Disease_Type); %HR(x=Disease_Status); %HR(x=Active_Therapy); /**Ensure uniform variable length prior setting datasets**/ *Determine max variable lengths from metadata; PROC SQL; CREATE TABLE temp AS SELECT DISTINCT * FROM ( SELECT DISTINCT name,type,max(length) as length,varnum FROM sashelp.vcolumn WHERE LIBNAME eq 'WORK' and substr(memname,1,3) eq '_PE' GROUP BY name,type ) ORDER BY varnum ; QUIT; *Generate attrib statement content. Uniform variable length - ensure no data is cut off; DATA _NULL_; LENGTH attrib $ 2000; SET temp end=last; BY varnum; RETAIN attrib ''; IF _N_ eq 1 THEN call missing(attrib); attrib=strip(attrib)||' '||strip(name); IF type eq 'char' THEN attrib=strip(attrib)||' length=$'||strip(put(length,best8.)); ELSE attrib=strip(attrib)||' length='||strip(put(length,best8.)); IF last THEN call symputx('gblattrib',attrib); RUN; %put &=gblattrib.; *output data; DATA out.ParameterEstimates; ATTRIB &gblattrib.; SET _PE:; RUN; *Clean up; %SYMDEL gblattrib; PROC DATASETS lib=work nolist; delete _PE: temp ParameterEstimates; RUN;QUIT; libname out clear;
- Cheers -
Hi, use ODS Output:
libname out xlsx "C:\want.xlsx"; %macro HR(x=); %let outputName=_PE%substr(%cmpres(&x.),1,%sysfunc(min(%length(&x.),29))); ods graphics off; ods output ParameterEstimates=&outputName.; proc phreg data = CP1; class &x; model Time*Event(0) = &x /rl; run; ods output close; ods graphics on; data out.&outputName.; set &outputName.; run; %mend HR; %HR(x=Gender); %HR(x=Disease_Type); %HR(x=Disease_Status); %HR(x=Active_Therapy);
- Cheers -
Hi @Oligolas ,
Thank you so much for the code! Could we optimize it and put all the HR(95%CI) in one single tab in the Excel? Maybe "append" all the HR(95% CI)? At the moment, the code exported all the HRs and 95% CIs into seperate tabs by outcome (gender, active therapy).
Thanks again!
Hi,
I see, try this:
libname out xlsx "C:\want.xlsx"; %macro HR(x=); %let outputName=_PE%substr(%cmpres(&x.),1,%sysfunc(min(%length(&x.),29))); ods graphics off; ods output ParameterEstimates=&outputName.; proc phreg data = CP1; class &x; model Time*Event(0) = &x /rl; run; ods output close; ods graphics on; %mend HR; %HR(x=Gender); %HR(x=Disease_Type); %HR(x=Disease_Status); %HR(x=Active_Therapy); /**Ensure uniform variable length prior setting datasets**/ *Determine max variable lengths from metadata; PROC SQL; CREATE TABLE temp AS SELECT DISTINCT * FROM ( SELECT DISTINCT name,type,max(length) as length,varnum FROM sashelp.vcolumn WHERE LIBNAME eq 'WORK' and substr(memname,1,3) eq '_PE' GROUP BY name,type ) ORDER BY varnum ; QUIT; *Generate attrib statement content. Uniform variable length - ensure no data is cut off; DATA _NULL_; LENGTH attrib $ 2000; SET temp end=last; BY varnum; RETAIN attrib ''; IF _N_ eq 1 THEN call missing(attrib); attrib=strip(attrib)||' '||strip(name); IF type eq 'char' THEN attrib=strip(attrib)||' length=$'||strip(put(length,best8.)); ELSE attrib=strip(attrib)||' length='||strip(put(length,best8.)); IF last THEN call symputx('gblattrib',attrib); RUN; %put &=gblattrib.; *output data; DATA out.ParameterEstimates; ATTRIB &gblattrib.; SET _PE:; RUN; *Clean up; %SYMDEL gblattrib; PROC DATASETS lib=work nolist; delete _PE: temp ParameterEstimates; RUN;QUIT; libname out clear;
- Cheers -
Hi, Thank you so much for the code, saving quite some time!
However, when I use the option for reference group:
class &x (ref='first') - it shows error, I really appreciate if you could show where to change in the code lines for it.
Thanks!
Hao
Hi,
well, I suspect you do not have a value of &x='first' in each of your &x variables.
You may need to determine the reference value for each of your variables.
I added such a dummy 'first' value in each of the variables in my test data and it worked, please find an example below.
data cp1;
set sashelp.class;
length Gender $5 Disease_Type $5 Disease_Status $8 Active_Therapy $5 Time 8 Event 8;
Gender=sex;
Disease_Type=ifc(sex eq 'M','One','Two');
Disease_Status=ifc(sex eq 'M','Resolved','Ongoing');
Active_Therapy=ifc(sex eq 'M','Y','N');
Time=age;
Event=mod(age,2);
*add a reference to all variables;
array vars _CHARACTER_;
do over vars;
if mod(_N_,3) eq 0 then vars='first';
end;
keep Gender Disease_Type Disease_Status Active_Therapy Time Event;
run;
- Cheers -
I tried your syntax, adding it in the data set before running all - wonder if this is correct but results came out the same with last value as reference not the first one. Do we need to adjust anything in 'data _NULL'?
Thanks!
hi,
you need to check for each of your variable what the reference should be. I added it for example purposes only. Consult a statistician to determine the reference.
- Cheers -
Thanks!
Hi Oligolas,
I know this topic was solved but my question is relevant to it, so I ask it here.
Your codes work great for proc phreg with time invarying covariates.
Can you help with codes for modeling multiple time varying covariates as below?
I have about 15 sets of variables (X, Y....) so it would be great not to repeat them 15 times.
Thank you!
proc phreg data=table1;
model TIME*outcome (0)=X/TIES = EFRON RL;
array pp{*} X1-X5;
array tt{*} t1-t6; t1=1; t2=2; t3=3; t4=4; t5=5; t6=6;
if TIME <tt[1] then X=X0;
else if TIME >= tt[6] then X=X6;
else do i=1 to dim(pp); if tt[i] <= TIME < tt[i+1] then X= pp[i];end;
run;
Hi,
not sure I understood you properly, you mean, you'd like to do the same proc phreg for the variable Y and so on like this?
proc phreg data=table1;
model TIME*outcome (0)=Y/TIES = EFRON RL;
array pp{*} Y1-Y5;
array tt{*} t1-t6; t1=1; t2=2; t3=3; t4=4; t5=5; t6=6;
if TIME <tt[1] then Y=Y0;
else if TIME >= tt[6] then Y=Y6;
else do i=1 to dim(pp); if tt[i] <= TIME < tt[i+1] then Y= pp[i];end;
run;
if yes then you only need to loop over the variables that you need:
%MACRO loop(varlist=x y z);
%local varlist i currItem;
%LET i=1;
%LET currItem=%SCAN(&varlist.,&i.,%STR( ));
%DO %WHILE(%LENGTH(&currItem.)>0);
proc phreg data=table1;
model TIME*outcome (0)=&currItem./TIES = EFRON RL;
array pp{*} &currItem.1-&currItem.5;
array tt{*} t1-t6; t1=1; t2=2; t3=3; t4=4; t5=5; t6=6;
if TIME <tt[1] then &currItem.=&currItem.0;
else if TIME >= tt[6] then &currItem.=&currItem.6;
else do i=1 to dim(pp); if tt[i] <= TIME < tt[i+1] then &currItem.= pp[i];end;
run;
%put &=varlist &=i &=currItem;
%LET i=%EVAL(&i.+1);
%LET currItem=%SCAN(&varlist.,&i.,%STR( ));
%END;
%MEND loop;
%loop(varlist=X Y Z);
- Cheers -
Yes, wonderful!
Thanks so much!
Hao
ods output ParameterEstimates= Est;
proc phreg data=have;
model AVAL*y(1)=sexn AGEGR1N/ALPHA=0.05 rl;
run;
hi , try the option -- ALPHA=0.05 rl
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.