Sas 使用前面的行向当前键添加行

Sas 使用前面的行向当前键添加行,sas,Sas,我知道标题有点难理解,对此我很抱歉。找不到更好的办法来解释我的问题 我有这样的想法: DATA HAVE; INPUT POLID PRODID TOSNUM PREMID X_INSURER_SERIAL_NO; DATALINES; 13102100206 310 0 20 . 13102100207 310 0 20 . 13102100207 310 0 21 . 13102100207 310 1 1 . 13102100207 310 1 2 . 13102100207 310

我知道标题有点难理解,对此我很抱歉。找不到更好的办法来解释我的问题

我有这样的想法:

 DATA HAVE;
 INPUT POLID PRODID TOSNUM PREMID X_INSURER_SERIAL_NO;
 DATALINES;
13102100206 310 0 20 .
13102100207 310 0 20 .
13102100207 310 0 21 .
13102100207 310 1 1 .
13102100207 310 1 2 .
13102100207 310 1 3 .
13102100207 310 1 20 .
13102100207 310 1 21 .
13102100207 310 2 1 .
13102100207 310 2 2 .
13102100207 310 2 20 .
13102100207 310 2 21 .
13102100207 310 3 1 .
13102100207 310 3 2 .
13102100207 310 3 9 .
13102100207 310 3 20 .
13102100207 310 3 21 .
13102100209 310 500 20 5
13102100210 310 100 20 1
13102100210 310 101 21 1
13102100210 310 100 1 1
13102100210 310 101 2 1
13102100210 310 101 3 1
13102100211 310 100 20 1
13102100211 310 101 21 1
13102100211 310 200 1 2
13102100211 310 201 2 2
13102100211 310 201 3 2
;RUN;
我需要做的是

如果当前行中缺少premid,但前一行中存在每个polid+prodid,则添加premid

比如说,, polid=13102100207,prodid=310

当tosnum=1时,我有5个不同的premid(1,2,3,20,21)。 当tosnum=2时,我有4个不同的premid(1,2,20,21)。缺少premid=3

我需要添加这个premid,并且每当我添加premid时,在虚拟索引列中添加1

例如,polid=13102100206, 只有一行,并且由于之前没有tosnum,因此应将therfor排除在计算之外

当X_保险公司序列号未丢失时,它应替换为tosnum

所以, 例如,polid=13102100210也应排除在计算之外, 因为它没有任何其他以前的值(x_\u serial_no始终等于1)

这就是我所做的:

首先,当x_保险公司序列号不丢失时,替换为tosnum:

PROC SQL;
CREATE TABLE AAA
AS
SELECT DISTINCT POLID, PRODID , 
CASE WHEN X_INSURER_SERIAL_NO = . THEN TOSNUM ELSE X_INSURER_SERIAL_NO END as  X_INSURER_SERIAL_NO 
FROM HAVE 
;QUIT;
那么

我使用下面的代码来确定计算中是否包含或排除polid:

PROC SQL;
CREATE TABLE BBB AS
SELECT POLID, PRODID, COUNT(*) AS COUNT
FROM AAA
GROUP BY 
POLID, PRODID
;QUIT;
我只对count>1的计算行使用

PROC SQL;
CREATE TABLE ABC AS
SELECT * FROM HAVE 
WHERE 
CATS(POLID,PRODID) IN 
SELECT CATS(POLID,PRODID) FROM BBB
WHERE COUNT>1;
QUIT;
现在我找到循环的最小值和最大值:

proc sql;
select min(TOSNUM), max(TOSNUM) ,  max(TOSNUM) -  min(TOSNUM) into: min_TOSNUM, :max_TOSNUM, :diff
from abc;
quit;
然后循环:

%宏虚拟premid(min_TOSNUM=,diff=)

proc-sql; 创建表虚拟\u premid 选择POLID、PRODID、TOSNUM、PREMID、0作为虚拟索引 来自美国广播公司 其中TOSNUM=&min\u TOSNUM; 退出

现在,

我的问题开始了,比如, 当&i的值=4时 polid=13102100207

因为last tosnum等于3, 我得到了6个tosnum=4的新行,其中虚拟的_ind=1。 当然,直到&i达到&diff的值,这种情况才会发生

我想问你的是

是一种在到达最后一个tosnum或x_保险公司序列号时停止评级的方法

非常感谢你的帮助


希望我能很好地解释我的需求。

如果我理解你的问题,我想这正是你想要的。这取决于TOSNUM值是增量的(即1、2、3或4、5、6),没有跳过

/*Overwrite TOSNUM with X_INSURER_SERIAL_NO
  if it exists*/
data have;
set have;
tosnum = coalesce(X_INSURER_SERIAL_NO,TOSNUM);
run;

proc sort data=have;
by POLID PRODID TOSNUM PREMID;
run;

proc sql noprint;
/*Find polid values to delete*/
create view dist as
select distinct polid,
       prodid,
       tosnum
    from have;

create table toDelete as
    select polid,
           count(*) as count
        from dist
        group by polid
        having count = 1;

/*Delete single values*/
delete from have
    where polid in
        ( select polid from toDelete );

create table lastTosnum as
select POLID, PRODID, max(TOSNUM)+1 as Tosnum
    from have
    group by POLID, PRODID;
quit;

/*Increment TOSNUM by 1*/
data nextVals;
set have(drop=X_INSURER_SERIAL_NO );
TOSNUM = tosnum + 1;
run;

/*Delete the last TOSNUM from the set above*/
proc sql noprint;
delete from nextVals as nv
    where nv.tosnum in
        (select tosnum
            from lastTosnum as lts
            where lts.polid = nv.polid
              and lts.prodid = nv.prodid
        );
quit;

/*Merge to get the final set.*/
data want;
merge have (in=h) nextVals (in=next);
by POLID PRODID TOSNUM PREMID;

if next and ^h then
    fictive_ind = 1;
else 
    fictive_ind = 0;
/*decrement tosnum*/
tosnum = tosnum-1;

run;

首先,非常感谢您的回复。您的解决方案的问题(实际上,我的也是…)是,我必须以某种方式保留每一行的原始tosnum。。。当我意识到我有一个巨大的问题时,我已经完成了代码的编写。老实说,不知道该怎么做:(回到这里,很抱歉耽搁了。如果TOSNUM值是增量的,就像我假设的那样,您可以将
TOSNUM=TOSNUM-1;
添加到最后一个数据步骤。我编辑了解决方案来显示这一点。
/*Overwrite TOSNUM with X_INSURER_SERIAL_NO
  if it exists*/
data have;
set have;
tosnum = coalesce(X_INSURER_SERIAL_NO,TOSNUM);
run;

proc sort data=have;
by POLID PRODID TOSNUM PREMID;
run;

proc sql noprint;
/*Find polid values to delete*/
create view dist as
select distinct polid,
       prodid,
       tosnum
    from have;

create table toDelete as
    select polid,
           count(*) as count
        from dist
        group by polid
        having count = 1;

/*Delete single values*/
delete from have
    where polid in
        ( select polid from toDelete );

create table lastTosnum as
select POLID, PRODID, max(TOSNUM)+1 as Tosnum
    from have
    group by POLID, PRODID;
quit;

/*Increment TOSNUM by 1*/
data nextVals;
set have(drop=X_INSURER_SERIAL_NO );
TOSNUM = tosnum + 1;
run;

/*Delete the last TOSNUM from the set above*/
proc sql noprint;
delete from nextVals as nv
    where nv.tosnum in
        (select tosnum
            from lastTosnum as lts
            where lts.polid = nv.polid
              and lts.prodid = nv.prodid
        );
quit;

/*Merge to get the final set.*/
data want;
merge have (in=h) nextVals (in=next);
by POLID PRODID TOSNUM PREMID;

if next and ^h then
    fictive_ind = 1;
else 
    fictive_ind = 0;
/*decrement tosnum*/
tosnum = tosnum-1;

run;