【问题标题】:SAS/SQL - find 3 or more occurences within a given timeframeSAS/SQL - 在给定时间范围内找到 3 个或更多事件
【发布时间】:2017-03-13 12:11:47
【问题描述】:

我有数十万行数据(如下例所示),其中包括帐号和拨打电话的日期。我需要找到在 7 天内拨打 3 次或更多电话的所有帐户。因此,对于下面的数据,它将返回帐户 1111111 和 3333333 的行。

account_number  call_date
1111111          1/1/2010
1111111          1/3/2010
1111111          1/3/2010
1111111          1/5/2010
2222222          1/10/2010
2222222          1/20/2010
3333333          1/7/2010
3333333          1/7/2010
3333333          1/7/2010

可能有一个简单的解决方案,但出于某种原因,我画了一个空白。任何帮助将不胜感激。

【问题讨论】:

  • 这在 SAS 中很棘手。我会使用retain 的数据步骤。
  • “7 天期间”是指“一年中的一周”还是“任何连续 7 天?”
  • 任意连续 7 天。例如,如果在 2010 年 1 月 1 日有一个电话。那么接下来的 7 天内需要再打 2 个电话。

标签: sql date sas proc-sql datastep


【解决方案1】:

这是使用data steplag 函数和by group 的替代答案。

proc sort data=have;
by acc_nbr call_date;
run;

data want(drop=count);
set have;
by acc_nbr call_date;
d2 = lag2(call_date);
format d2 date9.;
if first.acc_nbr then count = 1;
if count < 3 then d2 = .;
count + 1;
diff = call_date - d2;
if diff <= 7 and diff ne . then output;
run;

所有这一切都是使用lag2 函数,它从当前记录之前的两条记录中返回call_date 的值。接下来,我们说如果它是第一个帐号然后设置count = 1。接下来,如果计数小于 3,我们将值 d2 设置为缺失。这确保我们不会从单独的 by group 中获取日期值。最后,我们只是检查以确保call_dated2 之间的差异小于或等于7,然后输出该记录。

如果客户在 7 天内多次拨打超过 3 次电话,这将输出重复的帐号,因此如果您需要唯一值,可以使用 proc sql, select distinctproc sort nodupkey

【讨论】:

  • 这会在日志中抛出“生成的缺失值”注释,许多人将其视为错误。
【解决方案2】:

有趣的问题。以下是我认为我会做的:

输入数据。对于每个call_date,计算7天前的日期。

data have;
    input account_number : $char20.
          call_date : mmddyy10.;
    date_7_days_before = intnx('DAY',call_date,-7);

datalines;
1111111 1/1/2010
1111111 1/3/2010
1111111 1/3/2010
1111111 1/5/2010
2222222 1/10/2010
2222222 1/20/2010
3333333 1/7/2010
3333333 1/7/2010
3333333 1/7/2010
;
run;

整合当日来电。每个帐户按天计算的来电总数。

proc sql;
    create table consolidate_calls as
    select account_number,
           call_date,
           date_7_days_before,
           count(*) as calls
   from have
   group by account_number,
            call_date,
            date_7_days_before;
quit;

自行加入consolidated_calls如果b.call_datea.date_7_days_beforea.call_date的日期范围内,则组合在一起。

proc sql;
    create table want as
    select a.account_number,
           a.call_date format=mmddyy10.,
           a.calls as calls_that_day,
           sum(b.calls) as calls_last_7_days /*Number of calls on, or within 7 days of, the call_date*/
    from consolidate_calls as a
    left join consolidate_calls as b
    on a.account_number = b.account_number
    and b.call_date <= a.call_date 
    and b.call_date >= a.date_7_days_before
    group by a.account_number,
             a.call_date,
             a.calls
    ;
quit;

自我加入方法对我来说有点难以解释,但我相信这应该可行。

【讨论】:

    【解决方案3】:

    试试这个,看起来解决方案可以正确生成结果。

    准备数据

    data a;
        input account_number call_date :mmddyy.;
        format call_date ddmmyy10.;
    datalines;
    1 1/1/2010
    1 1/3/2010
    1 1/3/2010
    1 1/5/2010
    2 1/10/2010
    2 1/20/2010
    3 1/7/2010
    3 1/7/2010
    3 1/7/2010
    ;
    run;
    

    解决方案

    proc sql;
        select distinct a1.account_number
        from a a1, a a2, a a3
        where a1.account_number = a2.account_number 
            and a1.account_number = a3.account_number
            and a3.call_date > a2.call_date 
            and a2.call_date > a1.call_date 
            and a3.call_date < a1.call_date + 7;
    quit;
    

    【讨论】:

      【解决方案4】:

      与@J_Lard 的方法类似,您可以使用DIF 函数来计算变量与其滞后之间的差异。这稍微简化了代码。如果帐号是数字,您可以通过测试dif2(id)=0 and dif2(calldate)&lt;=7 找到感兴趣的记录,检查ID 是否与之前的两条记录相同,并且calldate 在7 天内。如果帐号不是数字,可以使用 id=lag2(id) and dif2(calldate)&lt;=7 。当然,这是假设数据已经排序。

      下面的代码添加了一个_DONE布尔值,用于跟踪一个ID是否已经被输出。

      data want (keep=id);
        set have;
        by id;
        retain _done; *boolean to flag when an id has already been output;
        if first.id then _done=0;
      
        if _done=0 and dif2(id)=0 and dif2(calldate) <= 7 then do;
          output;
          _done=1;
        end;
      run;
      

      【讨论】:

        猜你喜欢
        • 2016-04-09
        • 2023-03-03
        • 1970-01-01
        • 2011-05-24
        • 1970-01-01
        • 1970-01-01
        • 2019-09-04
        • 2017-01-19
        • 2015-10-07
        相关资源
        最近更新 更多