首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Macro-Output Query(Edit Check Macro)

Macro-Output Query(Edit Check Macro)

作者头像
Setup
发布于 2019-10-21 09:12:10
发布于 2019-10-21 09:12:10
1.1K0
举报

愉快的周末又要结束了,繁忙的周一也即将开始!小编今天给大家Share的一个Macro是关于临床数据清理中的一个实用性的Macro,SAS Edit Check Output Query. -- Setup

背景介绍

临床试验数据清洗

小编曾从事临床试验数据清洗编程的工作,

虽然跳槽换了title,但是暂时本质还是一样...后面应该会变。。。还是回到主题上来。

什么是数据清洗?

在临床试验中,对试验数据进行前期的清理与逻辑核查,一般在数据清洗完成后在进行数据库的Database Lock ,Lock后的DataSet在交由统计师以及相关的编程人员进行统计分析,出相应的TFL等。

清理的目的?

为了后期统计分析的效果与质量,不管是在CRO还是在药厂,一般都是会有专门的数据部门存在,负责数据的清理。今天这个Macro就是用来帮助数据清理的。

在说程序前,还是要说一个东西,DVP(Data Validation Plan,数据验证计划)是由数据部门的DM编写,里面的是对临床试验收集的数据点进行验证的规则及其描述,SAS Programmer/Database Designer会更具DVP来实现一条一条的Edit Check,Edit Check 又分Online 和offline俩种,由于今年EDC系统的更新换代,很多核查都以及Online了,对于Offline的核查多是paper的项目与一些Online实现不了的核查,通过Edit Check核查出来的东西叫做Query,回有DM反馈给研究者,再由研究者解答疑问或者反馈会正确的数据。

说了半天还没说这个Macro是干嘛的,这个Macro就是用来写Edit Check的,更加便捷的输出Query。


Macro可以干嘛

跨表单执行逻辑核查,自动抓取变量的值,统一输出样式,批量执行Edit Check等等。。(见下图Macro简单的使用描述)

Excel模板

执行Log

执行结果

看Code

小编也知道,Code排版肯定会很烂,不要着急,文章结尾会给大家附上百度网盘链接,可以直接下载Code与Template,程序也可以直接使用。。我好像太帅了~

%macroChkQueryOutput(CheckData=,ChkLib=,SubjidKey=,VisitKey=,PageKey=);

Optionsmsglevel=N nomprint nonotes;

%put ;

%put ;

%put 开始执行!;

%put ;

%put ;

/*获取待核查逻辑库下的变量并进行预处理找出包含Format的变量*/

Proc contentsdata=&ChkLib.._all_ Out=FMTData(keep=MEMNAME name FORMAT) noprint;run;

proc sortdata=FMTData out=FMTData nodupkey; by_all_;run;

data FMTData;/**/

set FMTData;

name=upcase(name);

ifmissing(FORMAT) or FORMAT='$' then delete;

FORMAT=cats(FORMAT,'.');

if FORMAT="YYMMDD." Then FORMAT="YYMMDD10.";

DName=cats(MEMNAME,'.',NAME);

Output=cats("put(",name,",",FORMAT,")");

DOutput=cats("{put(",Dname,",",FORMAT,")}");

run;

%let dsid=%sysfunc(open(FMTData));/*获取FMTData数据集的观测为替换变量做准备*/

%let FMT1=%sysfunc(attrn(&dsid,nobs));/*nobs为观测数*/

%let rc= %sysfunc(close(&dsid));

data _null_;

set FMTData;

call symput('FNM'||compress(put(_n_,best.)),strip(Dname));

call symput('FOM'||compress(put(_n_,best.)),strip(DOutput));

run;

/*预处理EC不规范*/

data &CheckData. &CheckData._e;

set &CheckData.;

Deugw=count(QUERY,'{');

Deugm=count(QUERY,'}');/*判断{}是否是成对出现以及QUERY中是否包含英文双引号*/

ifDeugw-Deugm^=0 then output &CheckData._e;

/* if count(QUERY,'"')>0 or Deugw-Deugm^=0 orcount(Description,'"')>0 thenoutput &CheckData._e;*/

else output&CheckData.;

drop Deugw Deugm;

run;

data _null_;

set&CheckData._e;

call symput('deug'||compress(put(_n_,best.)),strip(DVPCODE));

run;

%let dsid=%sysfunc(open(&CheckData._e));

%let nobs7=%sysfunc(attrn(&dsid,nobs));

%let rc= %sysfunc(close(&dsid));

proc deletedata=&CheckData._e;quit;

%do k=1%to &nobs7.;

%put EC中QUERY填写不规范的DVP:&&deug&k.(DVP中包含“{}”不是成对出现),请核实;

%put ;

%put ;

%end;

dataCheckData_1;

set &CheckData.;

Description=tranwrd(Description,'"', '""');

QUERY=tranwrd(QUERY,'"', '""');

Query=Cats('Cats("',QUERY,'")');

%do i=1%to &FMT1.;

QUERY=tranwrd(QUERY,"{&&FNM&i.}","&&FOM&i.");

%end;

QUERY=tranwrd(QUERY,"{", '",');

QUERY=tranwrd(QUERY,"}", ',"');

run;

proc sqlUNDO_POLICY=NONE;

create tableCheckData_1 as

selectdistinct *

from CheckData_1

;

quit;

data _null_;

setCheckData_1;

call symput('ChkMainDATA'||compress(put(_n_,best.)),strip(DOMAIN));/*创建宏变量:获取主数据集*/

call symput('ChkDvpCode'||compress(put(_n_,best.)),strip(DVPCODE));/*创建宏变量:获取DVP编号*/

call symput('ChkSEQ'||compress(put(_n_,best.)),strip(SEQ));/*创建宏变量:获取SEQ(针对同条DVP拆分多种情况)*/

call symput('ChkDesc'||compress(put(_n_,best.)),strip(Description));/*创建宏变量:获取DM给到的DVP描述*/

call symput('ChkCondt'||compress(put(_n_,best.)),strip(Condition));/*创建宏变量:获取核查条件*/

call symput('ChkQUERY'||compress(put(_n_,best.)),strip(QUERY));/*创建宏变量:获取输出QUERY描述部分*/

call symput('ChkOtherSet'||compress(put(_n_,best.)),strip(OtherSet));/*创建宏变量:获取垮表单数据集*/

run;

/*获取EC条数以便进行循环*/

%let dsid=%sysfunc(open(CheckData_1));

%let nobs1=%sysfunc(attrn(&dsid,nobs));

%let rc= %sysfunc(close(&dsid));

proc deletedata=work.CheckData_1 FMTDATA;quit;

%do i=1%to &nobs1.;/*建立循环:从第一条EC开始循环*/

%let CDataSet1=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,1,' ')));

%let CDataSet2=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,2,' ')));

%let CDataSet3=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,3,' ')));

%let CDataSet4=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,4,' ')));

%let CDataSet5=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,5,' ')));

%let CDataSet6=%sysfunc(compress(%qscan(&&ChkOtherSet&i.,6,' ')));

proc copyin=&ChkLib. out=Work; select&&ChkMainDATA&i. &&ChkOtherSet&i. ;run;

proc sqlUNDO_POLICY=NONE;/*where语句核查情况*/

create tableChk_Shun as

select &&ChkMainDATA&i...&SubjidKey.,&&ChkMainDATA&i...&VisitKey. ,&&ChkMainDATA&i...&PageKey. ,

"&&ChkDvpCode&i." as DVP_CODE length=200,"&&ChkDesc&i." as DECL length=2000,&&ChkQUERY&i.as Query length=2000

from&&ChkMainDATA&i.

%if%length(&CDataSet1.)^=0%then%do;

full join&CDataSet1. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet1..&SubjidKey.

%end;

%if%length(&CDataSet2.)^=0%then%do;

full join&CDataSet2. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet2..&SubjidKey.

%end;

%if%length(&CDataSet3.)^=0%then%do;

full join&CDataSet3. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet3..&SubjidKey.

%end;

%if%length(&CDataSet4.)^=0%then%do;

full join&CDataSet4. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet4..&SubjidKey.

%end;

%if%length(&CDataSet5.)^=0%then%do;

full join&CDataSet5. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet5..&SubjidKey.

%end;

%if%length(&CDataSet6.)^=0%then%do;

full join&CDataSet6. on &&ChkMainDATA&i...&SubjidKey.=&CDataSet6..&SubjidKey.

%end;

where &&ChkCondt&i.

;

quit;

dataCHK_DAI_&i.;

set Chk_Shun;

run;

proc deletedata=work.Chk_Shun &&ChkMainDATA&i. &&ChkOtherSet&i.;quit;/*删除过程中衍生数据集*/

%let dsid=%sysfunc(open(CHK_DAI_&i.));

%let nobs4=%sysfunc(attrn(&dsid,nobs));

%let rc= %sysfunc(close(&dsid));

%put DVPCODE=&&ChkDvpCode&i...&&ChkSEQ&i. 执行完毕! Run出Query条数:【&nobs4.】;

%end;

dataChk_Output;

set CHK_dai_1;

run;

proc deletedata=CHK_dai_1;quit;

%if &nobs1.>1%then%do;

%do i=2%to &nobs1.;

proc appendbase=Chk_Output data=CHK_dai_&i.;run;

proc delete data=work.CHK_dai_&i.;quit;

%end;

%end;

%let dsid=%sysfunc(open(Chk_Output));

%let nobs3=%sysfunc(attrn(&dsid,nobs));

%let rc= %sysfunc(close(&dsid));

%put ;

%put 总计 :执行EC核查条数:【&nobs1.】 RUN出QUERY条数:【&nobs3.】;

%put ;

;

%mend;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SAS程序分享号号号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Macro-SAS2XPT/XPT2SAS
1.proc cport 过程步,与之对应的是XPT生产SAS数据的方式proc cimport 。
Setup
2019/10/21
3.4K0
Macro-SAS2XPT/XPT2SAS
SAS-一个小程序获取某网ATC编码库~
关于获取网页信息,小编其实在很早就有写到SAS-爬取帖子下的邮箱,给他们发一封邮件...嗯,其实也就是通过获取网页代码,从网页代码中提取出需要信息~还是看一张截图(谷歌浏览器按F12即可查看也面代码)
Setup
2019/10/21
1.5K0
SAS-一个小程序获取某网ATC编码库~
Macro-csv2sas(可控制变量Length)
%macro csv_csv2sas(path=,csvname=,colmax=%str(10000),outds=,encoding=gb2312,varr=0,labelr=1,length=500);
Setup
2019/10/21
7860
Macro-csv2sas(可控制变量Length)
SAS-走近Log,实现程序的“风险控制”
从第一天学习SAS开始,就摆脱不了看SAS日志,每次运行完程序的第一件事,不是看程序运行的结果,而是点击一下Log页面,第二件事也不是去看结果,而是仔细的浏览Log里面,有没有红色的字体出现(ERROR),有没有绿色的字体出现(WARNING),接着在看有没有黑色的_ERROR_=1出现(出现这种情况,一般是你的数据不满足条件或者语法有问题,下面会有例子),接着还得再看看有没有蓝色的字体(XXX未初始化)出现。就目前小编主要看的也就这四种常见的问题。肯定是不全的,各位大神如有兴趣可以留言补充~
Setup
2019/10/21
3.6K0
SAS-RTF的合并【完善篇】
这一篇推文是针对上一篇推文,进行SAS程序与功能上的完善!点击此处将可跳转至上一篇推文:SAS-如何简单快捷的实现RTF合并。在上一篇推文推送后,有不少人都对RTF的合并感兴趣,并找到了小编。于是小编决定将RTF的合并完善一下,写成宏程序,以便有需要的朋友可以直接使用。
Setup
2019/10/20
4.3K1
SAS-如何找出数据集超长变量及观测,并自动进行变量的拆分...
前段时间有人给小编提了一个需求,找出数据集中长度超过200字节的变量,并对变量进行拆分...这个需求当然不难,但是还是分享给大家~主要最近没写啥程序,也就没学到啥新的技能...关于变量长度的拆分,我想也是一个常见的问题。
Setup
2019/10/20
4.1K0
SAS-Macro 中的那些语句(一)
说到Macro,那么就不得不说宏变量,宏变量的是啥呢?可以理解成和其它编程语言中的变量一样,在内存中创建了一个空间(给这个空间一个标记,宏变量的名称),然后将一些值放到这个内存空间中(这就是定义宏变量的过程),好吧,我是一个不善解释的人,没理解的还是自行百度领悟。那么就来看看如何来定义Macro变量。
Setup
2019/10/21
2.6K0
SAS-Macro 中的那些语句(一)
SAS-时药曲线的绘制(完)
本文是上一篇的推文的续篇,本篇推文将主要介绍GTL绘制受试者维度的时药曲线(画拼图),并分享小编刚出炉的,还热腾腾的自动画图的宏程序。点击
Setup
2019/10/20
3.5K0
SAS-临床试验中编码频数表的自动输出
今天要写的是关于SAS在临床试验中自动输出频数表的程序。在临床试验中,我们会对不良事件与合并用药进行医学编码,编码后,我们会对编码进行分级频数汇总。汇总表长的什么样子呢,来见下图!
Setup
2019/10/21
2.3K0
SAS-函数(三),这几个函数你都知道吗~
昨天最后的一个函数是Lag,那么今天的第一个函数是和昨天的lag很类似,Lag可以将前一条观测下移,然后求差值,那么今天这个函数是可以直接求上下观测的差值...下来看看这段代码...
Setup
2019/10/20
4.9K0
SAS Macro小技巧—获取文件路径
这样做的的好处是啥呢,每次运行数据或者数据集想实现自动存下来,这个时候就可以用SAS自动创建文件夹的方式来存储。
Setup
2019/10/21
4.9K0
SAS-新规试行下诞生的程序
昨日,《药物临床试验数据递交指导原则》(试行)版正式公布了,在小编阅读后,于是本文因时而生了。
Setup
2020/07/24
2.3K0
SAS-新规试行下诞生的程序
SAS-编程中的小技巧(三)
这又是一篇SAS编程中的小技巧,这次要说的是SAS中数据字典与Macro结合起来的使用技巧,以及数据集删除、保存等技巧....
Setup
2019/10/20
2.6K0
当+(加号)碰上input&Excel测量文本长度
2.SDTM.LB.LBSTREFC这个变量在IG3.2里是Perm,IG3.3里是Exp,IG3.4里是先改成Perm,然后把这个变量删掉了 https://www.cdisc.org/kb/known-issues/lbstrefc-core-attribute-should-not-have-been-expected-sdtmig-v3-3
归海刀刀
2024/02/05
2000
当+(加号)碰上input&Excel测量文本长度
SAS-一个小程序实现自动插入空白行~
前几天一个朋友问我如何快速的在数据集中指定位置插入空白记录。当时我也是愣了一下,以前实现输出制作排版都是在proc report输出时进行设置的,还真没在数据集中的指定位置添加空白行(proc report通过out=也可以实现,感觉又写麻烦)。所以呀,小编就写了一个小程序,来实现数据集中指定位置添加空白行!虽然程序的功能很单一,但是同样小编认为是这也是一个很有趣的程序,所以啊,小编就给大家分享一下下~
Setup
2019/10/21
2.3K1
SAS-给公众号做一个秩和检验
嗯,于是小编从公众号上下载了自2017年11月11日-2018年03月25日的公众号每日增粉相关的数据...接着小编就开始分组了,以500人为区间,分成3个组进行对照研究(group1:<=1000;group2:1000-1500;group3:1501-2000);小编这里想到了临床试验中比较常见的对连续变量进行的描述性统计分析的一个例子,因此,我就套用过来对我公众号每日增粉数量进行分析,并按照临床试验中出三线表的形式,将分析结果进行输出!结果如下:
Setup
2019/10/21
1.6K0
SAS-给公众号做一个秩和检验
SAS-这几个小语法真的很鸡肋吗?
我们在写程序对大量数据集批量操作的时候,如果有的数据集有某变量,有的数据集没有某变量,而这个变量也作为程序处理的关键变量...这个时候我们就需要来判断某数据集中此变量是否存在,如果不存在生成该变量....那么有什么办法来判断数据集中某变量是否存在呢?当然办法也是很多的,不过下面的办法我想算是一个比较快捷的方式...下面来看一段小编写的转置小代码~
Setup
2019/10/21
1.7K0
SAS-这几个小语法真的很鸡肋吗?
SAS-如何实现多选值FORMAT的添加
在处理数据时,有时候会遇见变量值为多选的情况,此时如果要给变量添加上format,就略微麻烦许多。今天小编打算分享一段针对此种情况自动生成format的程序。
Setup
2019/10/20
2.8K1
乱码的烦恼
近期有朋友问小编,proc report pretext posttext 输出标题脚注乱码,怎么解决。原来他编程的环境是utf8,标题脚注是中文的话出出来就会乱码,如下图所示:
Setup
2023/09/01
6230
乱码的烦恼
创建SAS Format的几种方法
不管是做AD还是TFL,我们经常会碰到要创建Format。当Format中条目不多时我们可以直接用PROC FORMAT来创建,但是当条目很多时,这种方法就不方便了。下面详细介绍其他几种方法:
专业余码农
2020/07/15
1.8K0
相关推荐
Macro-SAS2XPT/XPT2SAS
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档