我试图找到两个进程之间的平均时间。每条记录都是一个修复过程,包括零件ID,开始日期和结束日期。对于给定的ID,一次只能进行一个修复过程。请参阅以下示例数据:
ID START_DATE END_DATE
123 1/2/2006 2/3/2006
124 1/3/2006 4/2/2006
123 3/5/2006 3/7/2006
123 6/2/2006 6/4/2006
123 6/8/2006 6/9/2006
124 6/2/2006 6/4/2006
124 6/5/2006 6/9/2006
124 6/10/2006 6/12/2006
我需要的信息是给定ID的END_DATE和START_DATE之间的差异。例如,对于ID 123,其第一个过程和第二个过程之间的时间是3/5/2006 - 2/3/2006。如果列表更长,我会采取所有这些差异并取其平均值。
输出将是这样的:
ID AverageTime
123 4.3
124 2.3
我的方法是根据以下步骤创建一个宏:
我认为这样可行,但可能需要很长时间,因为有400k行。有没有办法在没有宏的情况下做到这一点?这个过程如何优化,因为我运行它的服务器非常慢?
答案 0 :(得分:2)
您可以在数据步骤和PROC方式中执行此操作。 使用LAG()查找以前的值。你不能在这里使用DIF(),因为你正在查看不同的变量。
data middle_step;
set have;
by id;
lag_end = lag(end_date);
duration = start_date-lag_end;
if first.id then duration=.;
run;
proc means data=middle_step mean;
class id;
var duration;
run;
答案 1 :(得分:1)
以下是“SAS-y”的做法。
首先是您的数据:
data have;
input ID START_DATE END_DATE;
informat start_date end_date mmddyy10.;
format start_date end_date mmddyy10.;
datalines;
123 1/2/2006 2/3/2006
124 1/3/2006 4/2/2006
123 3/5/2006 3/7/2006
123 6/2/2006 6/4/2006
123 6/8/2006 6/9/2006
124 6/2/2006 6/4/2006
124 6/5/2006 6/9/2006
124 6/10/2006 6/12/2006
;
按ID和Start_Date排序:
proc sort data=have;
by id start_date;
run;
接下来为每个id添加一个记录计数,并为前一个id添加一个链接。
data tmp;
set have;
by id;
if first.id then
id_cnt = 0;
id_cnt + 1;
id_last = id_cnt-1;
run;
然后将数据连接到自身,取第一个结束和下一个开始之间的差异的平均值:
proc sql noprint;
create table want as
select a.id
, mean(b.start_date - a.end_date) as ave
from tmp as a,
tmp as b
where a.id=b.id and
a.id_cnt=b.id_last
group by a.id;
quit;
答案 2 :(得分:1)
使用Dom的输入和排序,这个DOW循环将在一次通过中计算每个id的平均间隙:
... input ...
... sort ...
data want(keep=id gap_mean);
do _n_ = 1 by 1 until (last.id);
set have;
by id;
if prior_end then gap_sum = sum ( gap_sum, end_date - prior_end );
prior_end = end_date;
end;
gap_mean = gap_sum / (_n_ - 1); * number of gaps is the number of iterations less 1;
run;
注释的代码项目:
set
和by
语句在圈内_n_
跟踪循环迭代(方便 - 重用自动变量)until (last.id)
循环测试有效,因为每个组至少有一行,而标志设置在组的最后一行gap_sum
使用sum()
计算,因此第一个差距可以干净地累积。
... then gap_sum = gap_sum + end_date-prior_end
有效,但会导致LOG显示NOTE: Missing values were generated as a result of performing an operation on missing values.
... then gap_sum + (end_date - prior_date)
无需使用NOTE,但+
运算符会导致gap_sum
被隐式保留,这意味着gap_sum
必须在do
之前显式重置{1}} prior_end
是下一个的手动延迟gap_sum
和prior_end
答案 3 :(得分:0)
计算也可以在单个SQL查询中完成:
proc sql;
create table want as
select id,mean(dif) as mean_dif from(
select a.id,min(b.start_date-a.end_date) as dif
from have a,have b
where a.id=b.id
and a.end_date<b.start_date
group by a.id,a.start_date)
group by id;
run;
但是,如果重要的话,datastep解决方案可能会运行得更快。