SDTM.SV的感受

最近第一次做了SV数据集,记录一下自己的感受和想法。SV数据集包含了每个受试者每个访视的时间信息。个人理解可以想象成一个受试者都有一把尺子,尺子的两头分别是试验开始和结束的时间。而尺子上有许许多多个刻度,这些刻度就是每一个访视的开始和结束时间,也就是svstdtc和svendtc。对于受试者来说,每个访视之间不应该出现重叠,也就是一个访视的开始和结束时间内,不应该出现其他的刻度。


1657876866115.png

我们看一下SDTMIG上关于SV的变量有这些,变量并不多,其中最重要的就是SVSTDTC和SVENDTC了。
对于SVSTDTC和SVENDTC来说,可以使用之前提到的RFPENDTC的做法,使用retain语句和vcolumn数据集来生成获取所有时间信息的程序。但是应当至少注意一下几个数据,首先是既往用药,既往非药物治疗以及病史等过去史的问询,以及受试者的生日信息。

其次就是计划外访视的处理。对于计划外访视来说,首先要确定计划外访视以及计划外访视编号的命名规则。我遇到的几个项目一般都是寻找计划外访视发生前的最后一次访视,并以此确定访视名以及信息。

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的做法先做出访视结束时间,再依次类推做出结束时间。有几点需要注意的,首先是做的时候应该采用完整时间,避免出现缺失值。否则开始时间会变成缺失值。其次,相比RFPENDTC,我们做的时候应当保留原始数据中的访视名称以及出现的数据集名称。方便溯源以及之后做计划外访视的编号。

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;

接着合并访视开始与结束时间,并进行拆分。拆分为计划内访视和计划外访视。使用cross join将每个计划外访视与计划内访视进行合并,并比较。此处使用cross join时,应注意,需要在合并后筛选受试者编号相同的观测。保留计划外访视发生时间小于计划内访视的观测,并进行排序,得到差值最小的观测。这就是我们需要的计划外访视的名称前缀。最后与SDTM.DM进行合并,获取RFSTDTC信息,计算STDY和ENDY,就可以了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351