使用多个BY组SAS计算观察结果

时间:2016-08-09 17:20:52

标签: count sas

我正在研究大型EHR数据集中的处方模式。数据的结构使得我们可以获得几个关键信息,例如patient_num,encounter_num,ordering_date,药物,age_event(事件年龄)等。示例如下:

    Patient_num  enc_num  ordering_date  medication  age_event
        1111     888888     07NOV2008    Wellbutrin     48
        1111     876578     11MAY2011    Bupropion      50
        2222     999999     08DEC2009    Amitriptyline  32
        2222     999999     08DEC2009    Escitalopram   32
        3333     656463     12APR2007    Imipramine     44
        3333     643211     21DEC2008    Zoloft         45
        3333     543213     02FEB2009    Fluoxetine     45

目前,我有数据集按patient_id排序,然后按ordering_date排序,以便我可以看到每个人在遇到他们时以纵向方式处理的内容。目前,我最关心的是他们第一次就诊时所处方的处方。我写了一些代码来计算处方的数量,并且最初将后来的分析限制在RX = 1,但正如我们所看到的,这对于在同一次遭遇中具有多个脚本的人不起作用(患者2222)。

    data pt_meds_;
     set pt_meds;
     by patient_num;
     if first.patient_num then  RX = 1;
     else RX + 1;
    run;

     Patient_num  enc_num  ordering_date  medication  age_event  RX
        1111     888888     07NOV2008    Wellbutrin     48        1
        1111     876578     11MAY2011    Bupropion      50        2
        2222     999999     08DEC2009    Amitriptyline  32        1
        2222     999999     08DEC2009    Escitalopram   32        2
        3333     656463     12APR2007    Imipramine     44        1
        3333     643211     21DEC2008    Zoloft         45        2
        3333     543213     02FEB2009    Fluoxetine     45        3

我认为将遭遇号码重新编码为新变量更合适,以便它们反映类似于RX变量的样式。每次遭遇都列在1-n中,如果在同一次遭遇中制作了多个脚本,则会重复该次数。如下:

     Patient_num  enc_num  ordering_date  medication  age_event  RX   Enc_
        1111     888888     07NOV2008    Wellbutrin     48        1    1
        1111     876578     11MAY2011    Bupropion      50        2    2
        2222     999999     08DEC2009    Amitriptyline  32        1    1 
        2222     999999     08DEC2009    Escitalopram   32        2    1
        3333     656463     12APR2007    Imipramine     44        1    1
        3333     643211     21DEC2008    Zoloft         45        2    2
        3333     543213     02FEB2009    Fluoxetine     45        3    3

从我所看到的情况来看,使用2个BY组(patient_num& enc_num)的上述代码的变体可能是可能的,但我似乎无法得到它。我认为第一个。 /最后。代码需要排序,但如果我按enc_num排序,它们将不按时间顺序排列,因为遇到的数字是由系统生成的,并且取决于当时进入的所有其他遭遇。

我尝试执行以下代码(使用ordering_date代替因为它已经正确排序)但Enc_下的所有内容都打印为1.我确信我的逻辑完全错误。有什么想法吗?

    data pt_meds_test;
     set pt_meds_;
     by patient_num ordering_date;
     if first.patient_num; 
     if first.ordering_date then enc_ = 1;
     else enc_ + 1;
    run; 

2 个答案:

答案 0 :(得分:4)

<强>第一

如果数据排序正确或您在.First声明中使用.Last,则

NOTSORTED / BY标记不需要排序。如果BY语句中的变量未正确排序,那么BY语句将抛出错误并在遇到偏差时停止执行。像这样:

data class;
   set sashelp.class;
   by age;
   first = first.age;
   last = last.age;
run;

 ERROR: BY variables are not properly sorted on data set SASHELP.CLASS.
 Name=Alfred Sex=M Age=14 Height=69 Weight=112.5 FIRST.Age=1 LAST.Age=1 first=. last=. _ERROR_=1 _N_=1
 NOTE: The SAS System stopped processing this step because of errors.
 NOTE: There were 2 observations read from the data set SASHELP.CLASS.        

尝试使用此代码查看exacly .first / .last标记的工作原理:

data pt_meds_test;
   set pt_meds_;
   by patient_num ordering_date;

   fp = first.patient_num;
   lp = last.patient_num;
   fo = first.ordering_date;
   lo = last.ordering_date;
run;

<强>第二

这些condidions的工作方式与您的想法不同:

if expression;
  • 如果表达式为真,则在if之后继续执行下一条指令。
  • 否则返回数据开始步骤(无隐式输出)。这也意味着您的观察结果不会保留在输出中。

在大多数情况下,没有if的{​​{1}}相当于then。然而

  • where工作得更快,但仅限于来自您正在阅读的数据集的变量
  • where可用于任何类型的表达式,包括计算字段

更多信息:: IF Statement, Subsetting

<强>第三

我认为if功能可以成为你的衣服。

lag()

使用data pt_meds_test; set pt_meds_; by patient_num; retain enc_; prev_patient_num = lag(patient_num); prev_ordering_date = lag(ordering_date); if first.patient_num then enc_ = 1; else if patient_num = prev_patient_num and ordering_date ne prev_ordering_date then enc_ + 1; end; run; 功能,您可以查看vairalbe在previos观察中的价值,并将其与当前的值进行比较。 但要小心。 lag()不会从之前的观察中寻找变量值。它需要变量值并将其存储在大小为1的FIFO队列中。在下一次调用时,它会从队列中检索存储的值并在其中放入新值。 更多信息:LAG Function

答案 1 :(得分:0)

我不确定这是否会伤害你的其他分析,但是

proc freq data=pt_meds noprint; 
    tables patient_num ordering_date / out=pt_meds_freq;
run;

data pt_meds_freq2;
    set pt_meds_freq;
    by patient_num ordering_date;
    if first.patient_num;
run;