最近第一次做了SV數(shù)據(jù)集,記錄一下自己的感受和想法。SV數(shù)據(jù)集包含了每個受試者每個訪視的時間信息。個人理解可以想象成一個受試者都有一把尺子,尺子的兩頭分別是試驗開始和結(jié)束的時間。而尺子上有許許多多個刻度,這些刻度就是每一個訪視的開始和結(jié)束時間,也就是svstdtc和svendtc。對于受試者來說,每個訪視之間不應(yīng)該出現(xiàn)重疊,也就是一個訪視的開始和結(jié)束時間內(nèi),不應(yīng)該出現(xiàn)其他的刻度。

我們看一下SDTMIG上關(guān)于SV的變量有這些,變量并不多,其中最重要的就是SVSTDTC和SVENDTC了。
對于SVSTDTC和SVENDTC來說,可以使用之前提到的RFPENDTC的做法,使用retain語句和vcolumn數(shù)據(jù)集來生成獲取所有時間信息的程序。但是應(yīng)當(dāng)至少注意一下幾個數(shù)據(jù),首先是既往用藥,既往非藥物治療以及病史等過去史的問詢,以及受試者的生日信息。
其次就是計劃外訪視的處理。對于計劃外訪視來說,首先要確定計劃外訪視以及計劃外訪視編號的命名規(guī)則。我遇到的幾個項目一般都是尋找計劃外訪視發(fā)生前的最后一次訪視,并以此確定訪視名以及信息。
data test;
set sashelp.vcolumn;
where upcase(libname)="RAW" and upcase(type)="CHAR" and upcase(memname) ne "OH" and upcase(memname) ne "AE" and upcase(memname) ne "AH" and upcase(memname) ne "MH" and upcase(memname) ne "CM" and upcase(memname) ne "DS" and upcase(name) ne "BRTHDAT" and find(upcase(name),"DAT") ne 0 and find(upcase(label),"日期") ne 0;
keep libname memname name;
proc sort;
by memname name;
run;
data dat;
length memname2 memname3 dat $200;
retain memname2 ;
set test;
by memname name;
if first.memname then memname2=strip(name);
else memname2=strip(memname2)||" "||strip(name);
dat=strip(name);
memname3="raw."||strip(memname)||"(keep=subject instancename datapagename "||strip(memname2)||" rename=("||strip(dat)||"=DTC))";
run;
data dat1;
set dat end=last;
length memname4 $4000.;
retain memname4;
if _N_=1 then memname4=memname3;
else MEMNAME4 = strip(MEMNAME4)||" "||strip(MEMNAME3);
if last;
run;
proc sql noprint;
select memname4 into :dat from dat1;quit;
data dat_en;
set &dat.;
where dtc ne "";
time=input(dtc,??yymmdd10.);
svendtc=put(time,yymmdd10.);
if time ne .;
keep subject svendtc instancename datapagename time;
proc sort;
by subject instancename descending time;
proc sort nodupkey;
by subject instancename;
run;
使用RFPENDTC的做法先做出訪視結(jié)束時間,再依次類推做出結(jié)束時間。有幾點需要注意的,首先是做的時候應(yīng)該采用完整時間,避免出現(xiàn)缺失值。否則開始時間會變成缺失值。其次,相比RFPENDTC,我們做的時候應(yīng)當(dāng)保留原始數(shù)據(jù)中的訪視名稱以及出現(xiàn)的數(shù)據(jù)集名稱。方便溯源以及之后做計劃外訪視的編號。
data svdat;
merge dat_en dat_st;
by subject instancename;
run;
data svinp;
set svdat;
where find(instancename,"計劃外") = 0;
length visit $200;
if instancename ne "提前退出" then visit=instancename;
else visit="EOT";
visitnum=input(visit,vis.);
proc sort;
by subject;
run;
data uns;
set svdat;
where find(instancename,"計劃外") ^= 0;
svdtc=svstdtc;
proc sort;
by subject;
run;
proc sort data=uns out=sub(keep=subject) nodupkey;
by subject;
run;
data svp;
merge sub(in=a) svinp(in=b);
by subject;
if a and b;
rename subject=subject_;
run;
proc sql;
create table temp as select a.svdtc,a.subject,b.* from uns a cross join svp b;
quit;
data temp;
set temp;
if subject=subject_;
run;
data temp1;
set temp;
day=input(svdtc,yymmdd10.)-input(svendtc,yymmdd10.);
if day>=0;
proc sort;
by subject svdtc day;
proc sort nodupkey;
by subject svdtc;
run;
proc sort data=temp1 out=temp2;
by subject visitnum day;
run;
data temp3;
retain visn 0;
set temp2;
by subject visitnum day;
length unsvisit $200;
visn=visn+1;
if first.visitnum then visn=1;
unsnum=input((strip(put(visitnum,best.))||"."||strip(put(visn,best.))),best.);
unsvisit="計劃外訪視"||" "||strip(put(unsnum,6.1));
keep subject svdtc unsvisit unsnum;
run;
data temp4;
set temp3;
length svstdtc svendtc $200;
svstdtc=svdtc;
svendtc=svdtc;
rename unsvisit=visit unsnum=visitnum;
run;
data unssp;
set &dat.;
if find(instancename,"計劃外") ne 0;
proc sort;
by subject dtc datapagename instancename;
proc sort nodupkey;
by subject dtc datapagename;
run;
data unsp;
length svupdes $200;
retain svupdes "";
set unssp;
by subject dtc datapagename;
if first.dtc then svupdes=strip(datapagename);
else svupdes=strip(svupdes)||","||strip(datapagename);
if last.dtc;
dtc=put(input(dtc,yymmdd10.),yymmdd10.);
run;
proc sql noprint;
create table temp4_1 as select a.*,b.svupdes from temp4 a left join unsp b on a.subject=b.subject and a.svdtc=b.dtc;
quit;
接著合并訪視開始與結(jié)束時間,并進行拆分。拆分為計劃內(nèi)訪視和計劃外訪視。使用cross join將每個計劃外訪視與計劃內(nèi)訪視進行合并,并比較。此處使用cross join時,應(yīng)注意,需要在合并后篩選受試者編號相同的觀測。保留計劃外訪視發(fā)生時間小于計劃內(nèi)訪視的觀測,并進行排序,得到差值最小的觀測。這就是我們需要的計劃外訪視的名稱前綴。最后與SDTM.DM進行合并,獲取RFSTDTC信息,計算STDY和ENDY,就可以了。