/***********************/ /* Importing Stata data*/ /***********************/ %web_drop_table(WORK.REGDATA); FILENAME REFFILE '/home/u62459397/Reg_Project/AkramPaperV2.dta'; PROC IMPORT DATAFILE=REFFILE DBMS=DTA OUT=WORK.REGDATA; RUN; PROC CONTENTS DATA=WORK.REGDATA; RUN; %web_open_table(WORK.REGDATA); /* Relabeling gender from numeric (0,1) to factor sex=(male, female) */ DATA work.regdata; SET work.regdata; *FORMAT Sex 8.; IF gender = 0 THEN Sex = "Female"; IF gender = 1 THEN Sex = "Male"; RUN; /*************************/ /* Histograms of weekly minutes of habitual PA (Figure 1)*/ proc sgplot data=work.regdata; histogram TotPA / nbins=18 SCALE=count; xaxis label=""; run; /*** reading first 10 rows of data **/ PROC PRINT DATA=work.regdata(obs=10); RUN; /*** summary measures **/ PROC MEANS DATA=work.regdata; VAR age medCond TotPA ave_mvpa; RUN; /*** Median and quartiles **/ proc means data = work.regdata qntldef=1 median q1 q3; var age medCond TotPA ave_mvpa; run; /****** fitting models to COUNT DATA **********/ /*** outcome variable (TotPA) to fit on age and NCMC (medCond) **/ /* Standard linear regression model */ proc genmod data=work.regdata; model TotPA = age gender medCond; run; /* GLM: Poisson regression model */ proc genmod data = work.regdata; model TotPA = age gender medCond / dist=poisson; run; /* GLM: Quasi-Poisson regression model */ proc glimmix data = work.regdata; model TotPA = age gender medCond / link = log solution; _variance_ = _mu_; random _residual_; output out=work.regdata pred(ilink)=predqp; run; ods trace on; ods output FitStatistics=OutputFS; ods output OptInfo=OutputOpt; proc glimmix data=work.regdata; model TotPA = age gender medCond / link = log solution; _variance_ = _mu_; random _residual_; run; ods trace off; proc print data=OutputFS noobs; proc print data=OutputOpt noobs; run; /* AIC of Quasi Poisson regression*/ /* Storing estimated despersion parameter value, phi */ data _null_; set OutputFS; if Descr="Pearson Chi-Square / DF" then call symputx("phi", value); run; %put φ /* Storing number of parameters, npar */ data _null_; set OutputOpt; if Descr="Parameters in Optimization" then call symputx("npar", value); run; %put ∦ /* An alternative parametrization (often used in ecology) is by the mean mu, and size, the dispersion parameter, where prob = size/(size+mu). The variance is mu + mu^2/size in this parametrization. Storing these variables in data file */ data work.regdata; set work.regdata; /* the dispersion parameter*/ size=predqp/(&phi-1); /* probability, p */ proba = size/(size+predqp) ; /* Variance */ var1 = predqp + predqp*predqp/size; /* number of success rr is (check https://en.wikipedia.org/wiki/Negative_binomial_distribution) */ rr=predqp*predqp/(var1-predqp); /* negative binomial density */ nbdf = pdf('NEGB',totPA,proba,rr); /* log of negative binomial density values */ lognbdf=log(nbdf); run; proc sql; create table sumlognbdf as select sum(lognbdf) as sumaic from work.regdata; quit; /** AIC of quasi Poisson regession */ data jnk; set sumlognbdf; aicqp = 2*(&npar+1) - 2*sumaic; run; /*******************************************/ /* GLM: Negative binomial regression model */ proc genmod data = work.regdata; model TotPA = age gender medCond / dist=negbin; run; /*******************************************/ /*********** CONTINUOUS OUTCOME ***********/ /******* Plotting original (untransformed) and transformed MVPA ********/ /* Log and square root transformed MVPA */ data work.regdata; set work.regdata; log_mvpa = log(ave_mvpa); sqr_mvpa = sqrt(ave_mvpa); run; /*** Plotting original (untransformed) and transformed MVPA **/ proc sgplot data=work.regdata NOAUTOLEGEND; histogram ave_mvpa / nbins=15 SCALE=count name='mvpa'; xaxis label = 'Minutes of mvpa'; run; proc sgplot data=work.regdata NOAUTOLEGEND; histogram log_mvpa / nbins=15 SCALE=count name='logmvpa'; xaxis label = 'Log of minutes of mvpa'; run; proc sgplot data=work.regdata NOAUTOLEGEND; histogram sqr_mvpa / nbins=15 SCALE=count name='sqrtmvpa'; xaxis label = 'sqrt of minutes of mvpa'; run; /* Combine all plots. To create one page with multiple charts in SAS use following template */ proc template; define statgraph multiple_charts; begingraph; /* Define Chart Grid */ layout lattice / rows = 3 columns = 1; /* plot 1 */ layout overlay / xaxisopts=(label="Minutes of mvpa"); histogram ave_mvpa / nbins=15 SCALE=count; endlayout; /* plot 2 */ layout overlay / xaxisopts=(label="Log of minutes of mvpa"); histogram log_mvpa / nbins=15 SCALE=count; endlayout; /* Plot 3 */ layout overlay / xaxisopts=(label="Square-root of minutes of mvpa"); histogram sqr_mvpa /nbins=15 SCALE=count; endlayout; endlayout; endgraph; end; run; proc sgrender data=work.regdata template=multiple_charts; run; /****** fitting models to CONTINUOUS DATA **********/ /*** outcome variable (ave_mvpa) to fit on age, sex and NCMC (medCond) **/ /* Standard linear regression model */ proc genmod data=work.regdata ; model ave_mvpa = age gender medCond / dist=normal link=identity;; output out=work.regdata p=predlm; run; /*ods trace on; ods output ModelFit=Output; proc genmod data=work.regdata; model sqr_mvpa = age gender medCond / dist=normal link=identity ; run; ods trace off; proc print data=Output noobs; run;*/ /* Standard linear regression model on SQRT transformed mvpa */ ods output ModelFit=Output; proc genmod data=work.regdata; model sqr_mvpa = age gender medCond / dist=normal link=identity; output out=work.regdata p=predlmsqrt; run; /* storing predicted values in orignal scale */ data work.regdata; set work.regdata; /*in original scale */ prlmsqrt=(predlmsqrt*predlmsqrt); n=_n_; run; /* storing AIC value */ data _null_; set Output; if Criterion="AIC (smaller is better)" then call symputx("AIC", value); run; %put &AIC; /*CHECK log window*/ /* Calculating adjusted AIC for transformed model */ proc sql; create table tmp1 as select sum(log_mvpa) as sumlogmvpa from work.regdata; quit; proc sql; create table tmp2 as select max(n) as new_n from work.regdata; quit; data together; merge tmp1 tmp2; run; data together; set together; AdjAICsqrt = sumlogmvpa + 2*new_n*log(2) + &AIC; run; /************************************************************/ /* Standard linear regression model on LOG transformed mvpa */ ods output ModelFit=Output1; proc genmod data=work.regdata; model log_mvpa = age gender medCond / dist=normal link=identity; output out=work.regdata p=predlmlog; run; /* storing predicted values in original scale */ data work.regdata; set work.regdata; /*in original scale */ prlmlog=exp(predlmlog); run; /* storing AIC value */ data _null_; set Output1; if Criterion="AIC (smaller is better)" then call symputx("AIC_log", value); run; %put &AIC_log; /*CHECK log window*/ /* ## AIC of Log transformed MVPA */ data tmp; set together; AdjAIClog = 2*sumlogmvpa + &AIC_log; run; /***************************************/ /* GLM: Gamma regression with Log link */ proc genmod data = work.regdata; model ave_mvpa = age gender medCond / dist=gamma link=log; output out=work.regdata p=predglmg resraw=residgamma resdev=DevG; run; /* storing predicted values in original scale */ data work.regdata; set work.regdata; prglmg=predglmg; residg=DevG; run; /* GLM: Inverse gaussian regression with Log link */ proc genmod data = work.regdata; model ave_mvpa = age gender medCond / dist=igaussian link=log; output out=work.regdata p=predglmig resraw=residig resdev=DevIG; run; /* storing predicted values */ data work.regdata; set work.regdata; prglmig=predglmig; residig=DevIG; run; /* Plotting predicted and actual values from various models on original scale against age */ ods graphics on / attrpriority=none; proc sgplot data=work.regdata nowall noborder; styleattrs datasymbols=(trianglefilled circlefilled); scatter x=age y=ave_mvpa / group=sex markerattrs=(color=black size=5px) name="original"; series x=age y=predlm / group=sex lineattrs=(color=bip) markers; legenditem type=markerline name='PredLM' / label="LM" lineattrs=(pattern=Solid color=bip) markerattrs=(symbol=circle size=0px); series x=age y=prlmlog / group=sex lineattrs=(color=bio) markers; legenditem type=markerline name='PredlogLM' / label="log-LM" lineattrs=(pattern=Solid color=bio) markerattrs=(symbol=circle size=0px); series x=age y=prlmsqrt / group=sex lineattrs=(color=bigb) markers; legenditem type=markerline name='PredsqrtLM' / label="sqrt-LM" lineattrs=(pattern=Solid color=bigb) markerattrs=(symbol=circle size=0px); series x=age y=predglmg / group=sex lineattrs=(color=pink) markers; legenditem type=markerline name='PredGLMg' / label="GLM-gamma" lineattrs=(pattern=Solid color=pink) markerattrs=(symbol=circle size=0px); series x=age y=predglmig / group=sex lineattrs=(color=lightgreen) markers; legenditem type=markerline name='PredGLMig'/label="GLM-IG" lineattrs=(pattern=Solid color=lightgreen) markerattrs=(symbol=circle size=0px); keylegend "original"/ noborder type=markersymbol title ="Original" location=inside position=topleft across=1; keylegend "PredLM" "PredlogLM" "PredsqrtLM" "PredGLMg" "PredGLMig"/ exclude=("Male") noborder title ="Predicted" location=inside position=topright across=1 linelength=20; refline 0 / axis=y lineattrs=(color=black pattern=ShortDash); run; /* Comparing GLM-gamma with GLM IG using residuals vs fitted values plot */ proc template; define statgraph multiple_plots; begingraph; /* Define Chart Grid */ layout lattice / rows = 2 columns = 1; /* Chart 1 */ layout overlay / xaxisopts=(label="GLM-gamma") yaxisopts= (linearopts=(viewmin=-2.5 viewmax=2.5)); scatterplot x=predglmg y=residg / markerattrs=(color=black size=5px); referenceline y=0 / lineattrs=(color=black pattern=ShortDash); endlayout; /* Chart 2 */ layout overlay / xaxisopts=(label="GLM-IG") yaxisopts= (linearopts=(viewmin=-2.5 viewmax=2.5)); scatterplot x=predglmig y=residig / markerattrs=(color=black size=5px); referenceline y=0 / lineattrs=(color=black pattern=ShortDash); *yaxis values=(-2.5 to 2.5 by 0.5); endlayout; endlayout; endgraph; end; run; proc sgrender data=work.regdata template=multiple_plots; run;