SAS/SQL 分组并保留所有行
SAS/SQL group by and keeping all rows
我有一个这样的table,及时观察一些账户的行为,这里有两个账户acc_ids 1和22:
acc_id date mob
1 Dec 13 -1
1 Jan 14 0
1 Feb 14 1
1 Mar 14 2
22 Mar 14 10
22 Apr 14 11
22 May 14 12
我想创建一个列 orig_date
如果 mob=0
等于 date
并且如果 acc_id
组最小 date
acc_id
没有 mob=0
。
因此预期的输出是:
acc_id date mob orig_date
1 Dec 13 -1 Jan 14
1 Jan 14 0 Jan 14
1 Feb 14 1 Jan 14
1 Mar 14 2 Jan 14
22 Mar 14 10 Mar 14
22 Apr 14 11 Mar 14
22 May 14 12 Mar 14
第二个账号没有mob=0
观察,所以orig_date
按组设置为min(date)
。
有没有什么方法可以在 SAS 中实现这一点,最好是一步 proc sql
?
这是一个数据步骤方法
data have;
input acc_id date $ mob;
datalines;
1 Dec13 -1
1 Jan14 0
1 Feb14 1
1 Mar14 2
22 Mar14 10
22 Apr14 11
22 May14 12
;
data want;
do until (last.acc_id);
set have;
by acc_id;
if first.acc_id then orig_date=date;
if mob=0 then orig_date=date;
end;
do until (last.acc_id);
set have;
by acc_id;
output;
end;
run;
看起来很简单。只需以两种方式计算最短日期,然后使用 coalesce() 来选择您想要的那个。
首先让我们将您的打印输出转换为实际数据集。
data have ;
input acc_id date :anydtdte. mob ;
format date date9.;
cards;
1 Dec13 -1
1 Jan14 0
1 Feb14 1
1 Mar14 2
22 Mar14 10
22 Apr14 11
22 May14 12
;
要在 MOB=0 时查找 DATE,请使用 CAsE 子句。 PROC SQL 将自动将在 ACC_ID 级别计算的 MIN() 聚合结果重新合并到所有详细信息行。
proc sql ;
create table want as
select *
, coalesce( min(case when mob=0 then date else . end)
, min(date)
) as orig_date format=date9.
from have
group by acc_id
order by acc_id, date
;
quit;
结果:
Obs acc_id date mob orig_date
1 1 01DEC2013 -1 01JAN2014
2 1 01JAN2014 0 01JAN2014
3 1 01FEB2014 1 01JAN2014
4 1 01MAR2014 2 01JAN2014
5 22 01MAR2014 10 01MAR2014
6 22 01APR2014 11 01MAR2014
7 22 01MAY2014 12 01MAR2014
我有一个这样的table,及时观察一些账户的行为,这里有两个账户acc_ids 1和22:
acc_id date mob
1 Dec 13 -1
1 Jan 14 0
1 Feb 14 1
1 Mar 14 2
22 Mar 14 10
22 Apr 14 11
22 May 14 12
我想创建一个列 orig_date
如果 mob=0
等于 date
并且如果 acc_id
组最小 date
acc_id
没有 mob=0
。
因此预期的输出是:
acc_id date mob orig_date
1 Dec 13 -1 Jan 14
1 Jan 14 0 Jan 14
1 Feb 14 1 Jan 14
1 Mar 14 2 Jan 14
22 Mar 14 10 Mar 14
22 Apr 14 11 Mar 14
22 May 14 12 Mar 14
第二个账号没有mob=0
观察,所以orig_date
按组设置为min(date)
。
有没有什么方法可以在 SAS 中实现这一点,最好是一步 proc sql
?
这是一个数据步骤方法
data have;
input acc_id date $ mob;
datalines;
1 Dec13 -1
1 Jan14 0
1 Feb14 1
1 Mar14 2
22 Mar14 10
22 Apr14 11
22 May14 12
;
data want;
do until (last.acc_id);
set have;
by acc_id;
if first.acc_id then orig_date=date;
if mob=0 then orig_date=date;
end;
do until (last.acc_id);
set have;
by acc_id;
output;
end;
run;
看起来很简单。只需以两种方式计算最短日期,然后使用 coalesce() 来选择您想要的那个。
首先让我们将您的打印输出转换为实际数据集。
data have ;
input acc_id date :anydtdte. mob ;
format date date9.;
cards;
1 Dec13 -1
1 Jan14 0
1 Feb14 1
1 Mar14 2
22 Mar14 10
22 Apr14 11
22 May14 12
;
要在 MOB=0 时查找 DATE,请使用 CAsE 子句。 PROC SQL 将自动将在 ACC_ID 级别计算的 MIN() 聚合结果重新合并到所有详细信息行。
proc sql ;
create table want as
select *
, coalesce( min(case when mob=0 then date else . end)
, min(date)
) as orig_date format=date9.
from have
group by acc_id
order by acc_id, date
;
quit;
结果:
Obs acc_id date mob orig_date
1 1 01DEC2013 -1 01JAN2014
2 1 01JAN2014 0 01JAN2014
3 1 01FEB2014 1 01JAN2014
4 1 01MAR2014 2 01JAN2014
5 22 01MAR2014 10 01MAR2014
6 22 01APR2014 11 01MAR2014
7 22 01MAY2014 12 01MAR2014