Monday, November 9, 2020

Date format

 data ex;

  input startd endd;

  datalnes;

  20180312 20180430

  ;


proc sql;

  select startd, endd, input(put(endd,8.),yymmdd8.) - input(put(startd,8.),yymmdd8.) 

  from ex

  ;quit;

Wednesday, January 15, 2020

Exact CI for Risk Difference

proc freq;
  table TRT*Y / nocol nopercent riskdiff (cl=(wald exact)) ;
  weight n;
  exact riskdiff;
  run;

/* Newcombe CI */
proc freq;
  table strata*trt*y / riskdiff(cl=newcombe common) alpha=0.05;
run;

Wednesday, October 9, 2019

SQL - dictionary

/* look for tables, columns using LABEL */

PROC SQL;
  SELECT DISTINCT memname, NAME, LABEL, TYPE, LENGTH
  FROM DICTIONARY.COLUMNS
  WHERE UPPER(LIBNAME) EQ 'RAW' & UPPER(LABEL) like '%OUTPATIENT%'
; QUIT;

PROC SQL;
  SELECT DISTINCT NAME, LABEL, TYPE, LENGTH
  FROM DICTIONARY.COLUMNS
  WHERE UPPER(LIBNAME) EQ 'SDTM' & UPPER(MEMNAME) EQ 'AE'
; QUIT;


Wednesday, December 19, 2018

Clopper-Pearson (Exact) CI

data prop;
  input y @@;
  datalines;
  0 1 0 0 0 0 1 0
  ;
 
ods select none;
proc freq data=prop;
  tables y / binomial (exact level='1') alpha=0.05;
  ods output binomialcls=ci;
run;
ods select all;

proc print data=ci; run;

Tuesday, May 15, 2012

Array and Proc Transpose


/* using array instead of proc transpose */

data ex;
  array xx[5] x1-x5;
  array yy[5] y1-y5;

  input id $  x1 x2 x3 x4 x5 y1 y2 y3 y4 y5;

  do time=1 to 5;
    x=xx[time];
    y=yy[time];
    output;
  end;
  keep id time x y ;
  datalines;
01 3   2  4  7  4    3  5  2  2  5
02 9   3  7  5  3    2  6  4  3  8
;


Obs    id    time    x    y

  1    01      1     3    3
  2    01      2     2    5
  3    01      3     4    2
  4    01      4     7    2
  5    01      5     4    5
  6    02      1     9    2
  7    02      2     3    6
  8    02      3     7    4
  9    02      4     5    3
 10    02      5     3    8

Saturday, July 25, 2009

Independent t-test with PROC MIXED


proc ttest data=anorexia (where=(treat in ("Cont","CBT")));
class treat;
var prewt;
run;

/* equal variance */
proc mixed data=anorexia (where=(treat in ("Cont","CBT")));
class treat;
model prewt = treat;
run;

/* unequal variance */
proc mixed data=anorexia (where=(treat in ("Cont","CBT")));
class treat;
model prewt = treat / DDFM=Satterthwaite;
repeated / group=treat;
run;

Friday, July 24, 2009

Paired t-test with PROC MIXED


proc import datafile="C:\projects\Endocrine\CGMS\data\ex\anorexia.csv" out=anorexia
dbms=csv replace; getnames=yes;
run;

proc sql;
create table cbt_long as
select var1 as patient, 0 as time, prewt as y
from anorexia (where=(treat="CBT"))
union
select var1 as patient, 1 as time, postwt as y
from anorexia (where=(treat="CBT"))
;quit;

proc mixed data= cbt_long;
class patient;
model y = time / s;
random patient;
* repeated / subject=patient type=cs rcorr;
run;

/* Paired t-test with SQL */
proc sql;
select t(postwt-prewt) as t, prt(postwt-prewt) as p_value
from anorexia (where=(treat="CBT"))
;quit;

PROC SQL: functions

COUNT, FREQ, N: number of nonmissing values

NMISS: number of missing values

MIN: smallest value

MAX: largest value

RANGE: range of values

SUM: sum of values

SUMWGT: sum of the WEIGHT variable values(footnote 1)

AVG, MEAN: means or average of values

T: Student's t value for testing the hypothesis that the population mean is zero

PRT: probability of a greater absolute value of Student's t

USS: uncorrected sum of squares

CSS: corrected sum of squares

VAR: variance

STD: standard deviation

STDERR: standard error of the mean

CV: coefficient of variation (percent)

Thursday, July 16, 2009

array & output


%let ntime=288;
data series (drop=j);
array c(30) ;
array s(30);
do time=1 to &ntime;
do j=1 to 30;
c[j]=cos(2*3.141593*j* time/&ntime); s[j]=sin(2*3.141593*j* time/&ntime);
end;
output;
end;
run;

Sunday, May 17, 2009

SEM


data illfl (type=corr);
input _type_ $1-4 _name_ $6-13
exercise 15-20 hardy 22-27
fitness 29-34 stress 36-41
illness 43-48;
cards;
n 373 373 373 373 373
mean 40.90 0.00 67.10 4.80 716.7
std 66.50 3.80 18.40 6.70 624.8
corr exercise 1.00
corr hardy -0.03 1.00
corr fitness 0.39 0.07 1.00
corr stress -0.05 -0.23 -0.13 1.00
corr illness -0.08 -0.16 -0.29 0.34 1.00
;;;;


/* Confirmatory Factor Analysis */

proc calis data=illfl corr;
lineqs
hardy = p1 F1 + e1,
stress = p2 F1 + e2,
illness = p3 F1 + e3,
fitness = p4 F2 + e4,
exercise= p5 F2 + e5;
std
e1-e5 = vare1-vare5,
F1 = 1,
F2 = 1;
cov
F1 F2 = covf1f2;
VAR exercise fitness hardy stress illness;
run;


/* Exploratory Factor Analysis */

proc factor data=illfl method=ml scree priors=smc;
var hardy stress illness fitness exercise;
run;

proc factor data=illfl method=ml rotate=v n=2 reorder plot priors=smc;
var hardy stress illness fitness exercise;
run;

Thursday, April 23, 2009

Poisson vs. Logistic regression


data melanoma;
input age $ region $ cases total;
ltotal=log(total);
datalines;
35-44 south 75 220407
45-54 south 68 198119
55-64 south 63 134084
65-74 south 45 70708
75+ south 27 34233
<35 south 64 1074246
35-44 north 76 564535
45-54 north 98 592983
55-64 north 104 450740
65-74 north 63 270908
75+ north 80 161850
<35 north 61 2880262
;
proc genmod data=melanoma order=data;
class age region;
model cases = age region / dist=poisson link=log offset=ltotal;
run;

proc sql;
create table melanoma2 as
select age, region, 1 as resp, cases as count from melanoma union
select age, region, 0 as resp, total-cases as count from melanoma
;quit;

proc genmod data=melanoma2;
weight count;
class age region;
model resp=age region / dist=binomial link=logit;
run;

proc mixed


data bond;
input ingot metal $ pres @@;
datalines;
1 n 67.0 1 i 71.9 1 c 72.2
2 n 67.5 2 i 68.8 2 c 66.4
3 n 76.0 3 i 82.6 3 c 74.5
4 n 72.7 4 i 78.1 4 c 67.3
5 n 73.1 5 i 74.2 5 c 73.2
6 n 65.8 6 i 70.8 6 c 68.7
7 n 75.6 7 i 84.9 7 c 69.0
;

proc mixed data=bond method=reml;
class ingot metal;
model pres=metal;
random ingot;
lsmeans metal / diff=control('n') adjust=dunnett;
run;

/* by simulation */
lsmeans metal / diff=control("n") cl
adjust=simulate(report seed=4943838 cvadjust);

Saturday, October 27, 2007

format

/* formats.sas7bcat is saved under h:\temp */

libname ex 'h:\temp';

proc format library=ex;
value sev 1='mile'
2='moderate'
3='severe';
run;


/* To use the permanent format */
libname ff 'h:\temp';
options fmtsearch=(ff);

SAS/IML - something worth to remember

# sasdataset -> matrix
use sas_data;
read all into M; /* read all variables into a matrix M;
print M;

# matrix -> sasdataset
proc iml;
M={1 2 3, 4 5 6, 7 8 9};

create sas_data from M;
append from M
close sas_data

quit;

# pi
pi=constant('PI');

# rank of a matrix
rank=round(trace(ginv(a)*a));

proc glmpower


data exemplary;
do variety=1 to 2;
do exposure=1 to 3;
input height @@; output;
end;
end;
datalines; /* expected population means */
14 16 21
10 15 16
run;

proc glmpower data=exemplary;
class variety exposure;
model height=variety|exposure;
contrast "variety" variety 1 -1;
contrast "exp 1 vs 3" exposure 1 0 -1;
contrast "inter" variety*exposure 1 1 1, -1 -1 -1;
power stddev=5
ntotal=60
power=.;
plot x=n min=30 max=90;
run;

proc power - sample size & power

/* one sample t-test */

* power = ? ;
proc power;
onesamplemeans
alpha=0.05
sides=2
nullm=20
mean=22
stddev=4
ntotal=44
power=.;
run;

* sample size = ? ;
proc power;
onesamplemeans
alpha=0.01
sides=u /* U: upper one-sided, L: lower one-sided
nullm=20
mean=22
stddev=4
ntotal=.
power=0.8;
run;

/* paired t-test */
proc power;
pairedmeans test=diff
alpha=.01
sides=2
meandiff=3
stddev=3.5
corr=.2
npaires=20 30 40
power=.;
run;

/* independent t-test */
proc power;
twosamplemeans
meandiff=3 to 4 by .5 /* the same as 3 3.5 4 */
stddev=8 to 9 by .5
groupweights=(1 1)
power=0.8
ntotal=.;
plot y=power min=0.5 max=0.99;
run;

* a different way;
proc power;
twosamplemeans
groupmeans=(13 14) (13 14.5) (13 15) /* same as 13|14 14.5 15 */
stddev=1.2 1.7
groupweights=1|1 2 3 /* same as (1 1) (1 2) (1 3) */
power=0.8
ntotal=.;
run;

* Power vs Effect Size
proc power;
twosamplemeans test=diff
meandiff=0 to 2.5 by 0.5
stddev=.5657 1.0 1.4318
power=.
npergroup=10;
plot x=effect interpol=join;
run;

/* Multiple Regression */
proc power;
multreg
model=random
nfullpredictors=7
ntestpredictors=1
partialcorr=0.35
ntotal=100
power=.;
plot x=n min=50 max=150;
run;

/* One-way ANOVA */
proc power;
onewayanova test=overall
alpha=.05
groupmeans=(5 7 3 11)
stddev=4 5 6
npergroup=10 15
power=.;
run;

/* Normal Approximation to test a proportion */
proc power;
onesamplefreq test=z method=normal /* test=adjz with continuity corrrection */
sides=1 /* one-sided */
alpha=.05
nullproportion=0.3
proportion=.2
ntotal=.
power=.8;
run;

/* Fisher's exact test */
proc power;
twosamplefreq test=fisher
proportiondiff=0.10 to 0.15 by 0.01
refproportion=.2
npergroup=150
power=.;
run;

/* LR Chi-square Test for Two Proportions */
/* test=pchi for Pearson Chi-square Test for Two Proportions */
proc power;
twosamplefreq test=lrchi
proportiondiff=0.10 to 0.15 by 0.01
refproportion=.2
npergroup=150
power=.;
run;

/* Correlation */
proc power;
onecorr dist=fisherz
npvars=6
corr=.35
nullcorr=.2
sides=1
ntotal=100
power=.;
run;

/* comparing 2 survival curves */
proc power;
twosamplesurvival test=logrank
gexphs=0.3567 | 0.5978 .6931
grouplossexphazards=(0.3567 0.3567)
accrualtime=1
followuptime=1
groupweights=(1 2)
power=.
ntotal=225;
run;

/* TOST */
proc power;
twosamplemeans test=equiv_ratio
lower=.8
upper=1.25
meanratio=1 1.2
cv=.1 .2 .3
npergroup=.
power= .8 .9;
run;

Simple ODS

# Trace output
ods trace on / label;

proc mixed;
...
run;

ods trace off;

# use it
ods select none;
ods output LSMeans=lsm;
proc mixed;
...
run;
ods select all;

Thursday, October 25, 2007

first. & last.

/* For each family, ped_id starts with 1 */
data pedigree_id;
set family;
by id;
if first.id then ped_id=1;
else ped_id+1;
run;

/* using proc sql */
proc sql;
create table pedigree_id as
select family.*, monotonic() as _n_, calculated _n_-min(calculated _n_)+1 as ped_id
from family
group by id;
quit;

Small Tips

# print first 10 observations only
proc print data=aa (obs=10);

# apply more than 2 restrictions
proc print data=aa (keep=sex grade where=(sex='m'));

# substr
substr(var, position, length)

# get rid of duplications
proc sort data=aa nodupkey;
by id;

# merge summary statistics
data combined;
if _n_=1 then set summary;
set detail;
run;

# coalesce & coalescec : first non-missing
x = coalesce( ., 42, 52)
x = coalescec ('', 'Goodbye', 'Hello')

# get rid of characters after '.' or '('
loc=indexc(crfpage,'.','(');
if loc>0 then crfpage=substr(crfpage,1,loc-1);


# combine strings
data comb_txt;
input id $4. +1 categry $7.;
aa = compress(categry," ,");
n=length(aa);
cat=substr(aa,1,1);
do i=2 to n;
cat=trim(left(cat))||", "||substr(aa,i,1);
end;
cards;
0149 2, 5
0148 7,
0150 8, 5
0151 3, 4, 6
0152

proc freq

## proc freq oder = data;

## No column totals, row totals and percent
tables var1*var2 / nocol norow nopercent;

## Odds Ratio and Relative Risk
tables var1*var2 / CMH;

## McNemar's test and Kappa
tables var1*var2 / AGREE;

## obtain cell counts
proc freq data= data_name;
tables var1*var2*var3 / sparse out= out_name;