对数据集SAS中的连续观测值求和



我有一个数据集,看起来像:

Hour    Flag
1       1
2       1
3       .
4       1
5       1
6       .
7       1
8       1 
9       1
10      . 
11      1
12      1
13      1
14      1

我想要一个输出数据集,比如:

Total_Hours   Count
2          2
3          1
4          1

正如你所看到的,我想用连续的";1s";。缺少值将结束连续序列。

我该怎么做?谢谢

您需要分两个步骤来完成此操作。第一步是确保数据正确排序,并确定连续时段的小时数:

PROC SORT DATA = <your dataset>;
BY hour;
RUN;
DATA work.consecutive_hours;
SET <your dataset> END = lastrec;
RETAIN
total_hours 0
;
IF flag = 1 THEN total_hours = total_hours + 1;
ELSE
DO;
IF total_hours > 0 THEN output;
total_hours = 0;
END;
/* Need to output last record */
IF lastrec AND total_hours > 0 THEN output;
KEEP 
total_hours
;
RUN;

现在有一个简单的SQL语句:

PROC SQL;
CREATE TABLE work.hour_summary AS
SELECT
total_hours
,COUNT(*) AS count
FROM
work.consecutive_hours
GROUP BY
total_hours
;
QUIT;

您必须做两件事:

  • 计算行程长度
  • 计算运行长度的频率

对于使用隐含循环的情况

  • 每次运行长度发生可以在一个保留的跟踪变量中计算和维护,测试output的缺失值或数据结束,以及运行长度重置或增量的非缺失值
  • 过程FREQ

另一种选择是使用显式循环和哈希进行频率计数。

示例:

data have; input
Hour    Flag; datalines;
1       1
2       1
3       .
4       1
5       1
6       .
7       1
8       1
9       1
10      .
11      1
12      1
13      1
14      1
;
data _null_;
declare hash counts(ordered:'a');
counts.defineKey('length');
counts.defineData('length', 'count');
counts.defineDone();
do until (end);
set have end=end;
if not missing(flag) then 
length + 1;
if missing(flag) or end then do;
if length > 0 then do;
if counts.find() eq 0 
then count+1;
else count=1;
counts.replace();
length = 0;
end;
end;
end;
counts.output(dataset:'want');
run;

替代

data _null_;
if _N_ = 1 then do;
dcl hash h(ordered : "a");
h.definekey("Total_Hours");
h.definedata("Total_Hours", "Count");
h.definedone();
end;
do Total_Hours = 1 by 1 until (last.Flag);
set have end=lr;
by Flag notsorted;
end;
Count = 1;
if Flag then do;
if h.find() = 0 then Count+1;
h.replace();
end;
if lr then h.output(dataset : "want");
run;

几周前,@Richard教我如何使用DOW循环和直接寻址数组。今天,我把它送给你。

data want(keep=Total_Hours Count);
array bin[99]_temporary_;
do until(eof1);
set have end=eof1;
if Flag then count + 1;
if ^Flag or eof1 then do;
bin[count] + 1;
count = .;
end;
end;
do i = 1 to dim(bin);
Total_Hours = i;
Count = bin[i];
if Count then output;
end;
run;

再次感谢Richard,他还向我推荐了这篇文章。

最新更新