我有数十万行数据(如下例所示),其中包括帐号和已拨打的电话日期。我需要查找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
可能有一个简单的解决方案,但出于某种原因,我正在画一个空白。任何帮助将不胜感激。
答案 0 :(得分:1)
以下是使用data step
和lag
函数以及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_date
和d2
之间的差异小于或等于7并输出该记录。
如果客户在7天内多次拨打3次以上的电话,则会输出重复的帐号。如果您想要唯一值,则可以使用proc sql, select distinct
或proc sort nodupkey
。
答案 1 :(得分:1)
有趣的问题。以下是我认为我会做的事情:
输入数据。对于每个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_date
位于a.date_7_days_before
和a.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;
自我加入方法对我来说有点难以解释,但我相信这应该有用。
答案 2 :(得分:0)
试试这个,看起来解决方案可以正确生成结果。
准备数据
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;
答案 3 :(得分:0)
与@ J_Lard的方法类似,您可以使用DIF
函数计算变量与其滞后之间的差异。这简化了代码。如果帐号是数字,您可以通过测试dif2(id)=0 and dif2(calldate)<=7
找到感兴趣的记录。它检查ID是否与之前的两个记录相同,并且该校准在7天内。如果帐号不是数字,可以使用id=lag2(id) and dif2(calldate)<=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;