如何解决SAS 上的 (PROC) SQL 中的条件总和语句/分组依据
我正在使用 SAS
在 (PROC) SQL
工作,我有以下数据集:
ID Date Time Delta_Time
x 01/01/2019 121500 0
x 01/01/2019 121630 130
x 01/01/2019 122005 375
x 01/01/2019 154745 32740
x 01/01/2019 155905 1160
y 01/04/2019 132356 0
在此示例中,ID x
对 01/01/2019
执行 5 个操作。我想知道的是,只要 Delta_Time
不超过某个值,例如,每个 ID 执行后续操作的时长1500
。对于此示例,结果应如下所示:
ID Date Time
x 01/01/2019 505
x 01/01/2019 1160
Y 01/04/2019 0
我对 SQL
有基本的了解,但对 do loops
、data steps
和 if statements
不熟悉。
我应该如何解决这个问题?
解决方法
产生你说你想要的输出。如果有更多示例数据就好了。
data t;
infile cards firstobs=2;
input id:$1. date:mmddyy. time delta;
format date mmddyy.;
datalines;
ID Date Time Delta_Time
x 01/01/2019 121500 0
x 01/01/2019 121630 130
x 01/01/2019 122005 375
x 01/01/2019 154745 32740
x 01/01/2019 155905 1160
y 01/04/2019 132356 0
;;;;
run;
proc print;
run;
data t;
set t;
by id date;
delta_time=delta;
if first.date then g=0;
if delta gt 1500 then do;
g+1;
delta_time=.;
end;
run;
proc print;
run;
proc means n sum;
class id date g;
var delta_time;
run;
,
这只是一个group by
:
proc sql;
select id,date,sum(time)
from t
group by id,date;
run;
,
这是一个完整的数据步骤方法。
你不需要循环,一个数据步骤有一个内置循环,所以更了解数据步骤循环和IF语句的逻辑。
下面评论的代码和解决方案 - 我实际上不确定这会在所有情况下都有效,特别是对于最后一条记录,但它适合所示的用例。如果它不起作用,请扩展您的示例数据以包含更多相关用例。
data have;
infile cards;
informat ID $1. Date mmddyy10. Time 8. Delta_Time 8.;
format ID $1. Date mmddyy10. Time 8. Delta_Time 8.;
input ID $ Date Time Delta_Time;
cards;
x 01/01/2019 121500 0
x 01/01/2019 121630 130
x 01/01/2019 122005 375
x 01/01/2019 154745 32740
x 01/01/2019 155905 1160
y 01/04/2019 132356 0
;;;;
run;
*WANT is output data set created;
data want;
*Have is input data set provided (above);
set have;
by ID date;
*values you want to hold across rows;
retain running_total ;
*for the first of every date (within ID) set the running_total to 0;
if first.date then
running_total=0;
*If the value is gratehr than 1500 and not the first record then do the following;
if delta_time > 1500 & not first.Date then
do;
*write a line to new data set with previous running_total value;
output;
*reset running_total;
running_total=0;
end;
else /*continue to carry sum down otherwise*/
running_total=sum(running_total,delta_time);
*if you are on the last id,and value is less than 1500 you need to output it;
if last.Id and delta_time < 1500 then output;
run;
,
DATA + SQL 方法
您可以使用 DATA
步骤创建包含基于阈值标准的计算合成组的视图。使用 SQL 中的视图可以快速轻松地理解。我和@Tom 在之前的问题中多次演示了这种方法。
示例:
计算出的组值放在名为 section 的变量中,以防止新手编码员可能做出错误的假设。 我也喜欢将进入总和的值的数量相加。
data have;
infile cards;
attrib
id length=$1
date informat=mmddyy10. format=mmddyy10.
; input
ID Date Time Delta_Time; cards;
x 01/01/2019 121500 0
x 01/01/2019 121630 130
x 01/01/2019 122005 375
x 01/01/2019 154745 32740
x 01/01/2019 155905 1160
y 01/04/2019 132356 0
;
data have_sections / view=have_sections;
set have;
by id date;
if first.date then section+1;
if delta_time > 1500 then do;
section+1;
delete;
end;
run;
proc sql;
create table want(drop=section) as
select id,section,sum(delta_time) as section_total_time,count(*) as section_row_count
from have_sections
group by id,section
order by id,section
;
视图
最终结果
DOW 循环方法
循环每个 ID
DATE
组并在超过阈值时有条件地输出段。
data want;
do until (last.date);
set have;
by id date;
if delta_time > 1500 then do;
if not missing(sum) then output;
call missing(sum,count);
end;
else do;
sum = SUM(sum,delta_time);
count = SUM(count,1);
end;
end;
if not missing(sum) then output;
run;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。