【问题标题】:Subsetting Data Using Proc SQL使用 Proc SQL 对数据进行子集化
【发布时间】:2021-12-06 15:17:42
【问题描述】:

我对 SAS 还很陌生,正在做一个排序练习来提高我的 SAS 技能,但我似乎一直卡住,因为这个数据集有不同日期范围的观察结果。

我获得了访问两家不同医院的患者的生成入院和出院数据。数据按入学日期排序,并包含在一个数据集中。我的目标是从这个大型数据集创建两个数据集。第一个数据集应包含在访问医院 B 之前去过医院 A 的患者的患者 ID。第二个数据集应包含在访问医院 A 之前去过医院 B 的患者的患者 ID。主要样本数据集如下所示:

ID  Hospital Admission_Date Discharge_Date
1   A        21AUG2018      24AUG2018
1   A        02OCT2019      07OCT2019
1   B        07OCT2019      17OCT2019
2   B        01AUG2020      13AUG2020
2   A        28SEP2020      30SEP2020
3   B        17MAY2019      18MAY2019
3   A        18MAY2019      21MAY2019
3   B        21MAY2019      31MAY2019

生成的两个数据集应仅包含患者 ID。 例如,对于患者从医院 A 到医院 B 的数据集,我们应该有这样的内容:

ID
1

对于患者从医院 B 到医院 A 的情况,我们应该有这样的情况:

ID
2
3

对此的任何帮助将不胜感激!

【问题讨论】:

    标签: sql date sas proc-sql


    【解决方案1】:

    在 SQL 中,它看起来像这样:

    proc sql;
        create table a_to_b as
            select distinct a.id 
            from have as a
               , have as b
            where  a.id = b.id 
               AND a.hospital = 'A' 
               AND b.hospital = 'B'
               AND b.admission_date GE a.discharge_date
        ;
    
        create table b_to_a as
            select distinct a.id 
            from have as a
               , have as b
            where  a.id = b.id 
               AND a.hospital = 'A' 
               AND b.hospital = 'B'
               AND a.admission_date GE b.discharge_date
        ;
    quit;
    

    数据步骤版本只需要一次通过。它假定您的数据已经按正确的顺序排序,并将前一行与当前行进行比较。如果有任何 ID 从 A 到 B 或 B 到 A,我们将该 ID 的标志设置为 1 并停止进一步比较。当我们到达该 ID 的最后一个值时,我们将输出到相应的数据集。

    data a_to_b
         b_to_a
         ;
    
        set have;
        by id;
        retain flag_a_to_b flag_b_to_a;
    
        lag_hospital       = lag(hospital);
        lag_discharge_date = lag(discharge_date);
    
        if(first.id) then call missing(of lag:, of flag:);
    
        if(flag_a_to_b < 1) then flag_a_to_b = (    hospital     = 'B' 
                                                AND lag_hospital = 'A' 
                                                AND admission_date GE lag_discharge_date
                                               )
        ;
    
        if(flag_b_to_a < 1) then flag_b_to_a = (    hospital     = 'A' 
                                                AND lag_hospital = 'B' 
                                                AND admission_date GE lag_discharge_date
                                               )
        ;
    
        if(last.id AND flag_a_to_b) then output a_to_b;
        if(last.id AND flag_b_to_a) then output b_to_a;
    
        keep id;
    run;
    

    我们是如何得出 SQL 代码的

    SAS 中的 SQL 不能执行延迟,因此我们对两个 ID 进行内部连接,但获取医院 A 和 B 之间的所有入院和出院组合。看起来像这样:

    从这张表中,我们知道:

    1. hospital_a 必须是“A”,hospital_b 必须是“B”
    2. 一家医院的入院日期必须>=另一家医院的出院日期

    知道了这一点,我们得出以下where 子句:

    A 到 B:

        a.id = b.id 
    AND a.hospital = 'A' 
    AND b.hospital = 'B'
    AND b.admission_date GE a.discharge_date
    

    B 到 A:

        a.id = b.id 
    AND a.hospital = 'A' 
    AND b.hospital = 'B'
    AND a.admission_date GE b.discharge_date
    

    【讨论】:

    • 感谢您非常清楚的解释!这正是我想要做的,因为你,我学到了一些新东西:)
    • 查看示例数据集的输出后,我发现两个数据集上都有一些 ID。我怎样才能使每个唯一 ID 仅用于 1 个数据集?
    • 我猜在这种情况下,您需要确定 ID 如何输入数据的规则。例如,如果患者 3 从 B 到 A,从 A 到 B,哪个优先?
    • 我认为这里的规则是无论患者从 A 到 B,然后再从 B 到 A,首先发生的事情都是唯一要考虑的情况。所以如果患者 Z 从 A 到 B然后从 B 到 A 那么我们只关心从 A 到 B 的初始过渡。这有意义吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多