SAS:最常见的值(如 MODE)关系由新近度解决?
SAS: Most frequent value (Like a MODE) ties solved by recency?
我有这样的数据:
data mydata;
input ID $ Val $ Date;
datalines;
1 A 2010-12-01
1 B 2010-12-03
1 A 2010-12-04
1 B 2010-12-08
2 X 2009-10-01
2 X 2009-10-02
2 Z 2009-10-03
;
run;
我希望模式在它存在的地方返回。但是,ID 1 没有真模式。在模式不存在的关系的情况下,我希望最近的 Val 打破关系(如 id 1)。
期望的输出:
ID Mode
1 B
2 X
我试过 proc univariate(它只处理数字模式,另一个问题)但是这给出了模式为 null 的数据集;哪个 SAS 正确但不是所需的输出。我想在数据步骤中执行此操作。
代码:
proc univariate data=mydata noprint;
class id;
var val;
output out=modetable mode=mode;
run;
输出:
ID Mode
1
2 X
使用 proc 中的 IDgroup 意味着
此语句的示例可以在 Identifying the Top Three Extreme Values with the Output Statistics
中找到
让我们稍微扩展一下示例数据;
data myInput;
infile datalines dsd delimiter='09'x;
input
@1 ID 1.
@4 Val .
@7 Date yymmdd10.;
format Date yymmdd10.;
datalines;
2 X 2009-10-01
2 X 2009-10-02
2 Z 2009-10-03
3 C 2010-10-01
3 B 2010-10-03
3 A 2010-10-04
3 A 2010-12-01
3 B 2010-12-03
3 C 2010-12-04
;
run;
现在让我们计算每个“ID”的每个“Val”的频率和最后一次出现;
proc sql;
create view myView as
select ID, Val, max(Date) as Date format=yymmdd10., count(*) as freq
from myInput
group by ID, Val;
run;
最后,为每个 ID 保留一个 Val,优先选择出现频率高的那个,在出现频率相同的情况下选择最近的那个;
proc means data=myView nway noprint;
class ID;
output out=myModes(keep= ID Mode)
idgroup( max(freq Date) out[1] (Val)=Mode);
run;
proc print data=myModes;
run;
结果是;
ID Mode
2 X
3 C
这是我想出的 proc sql 解决方案,尽管我更喜欢所选的解决方案:
%macro modes(data, mode , tie , break, outset , lib );
proc sql;
create table &lib..&outset as
select &id, &mode
from (select &id, &mode, latest
from(select &id, &mode, latest
from(select &id, &mode, count(*) as n, &break.(&tie) as latest
from &data
where &mode is not null
group by &id, &mode)
group by &id
having n = max(n))
group by &id
having latest= &break.(latest) )
;
quit;
%mend modes;
%modes(data=mydata, mode=age , tie=somedateorvalue , break=max, outset=outtable , lib =mylib);
- Tie : 是用来打破平局的列
- break :如果您希望最早或最晚日期或高值或低值与
断开联系,则应为最小值或最大值
其余的应该是不言自明的。
我有这样的数据:
data mydata;
input ID $ Val $ Date;
datalines;
1 A 2010-12-01
1 B 2010-12-03
1 A 2010-12-04
1 B 2010-12-08
2 X 2009-10-01
2 X 2009-10-02
2 Z 2009-10-03
;
run;
我希望模式在它存在的地方返回。但是,ID 1 没有真模式。在模式不存在的关系的情况下,我希望最近的 Val 打破关系(如 id 1)。
期望的输出:
ID Mode
1 B
2 X
我试过 proc univariate(它只处理数字模式,另一个问题)但是这给出了模式为 null 的数据集;哪个 SAS 正确但不是所需的输出。我想在数据步骤中执行此操作。
代码:
proc univariate data=mydata noprint;
class id;
var val;
output out=modetable mode=mode;
run;
输出:
ID Mode
1
2 X
使用 proc 中的 IDgroup 意味着
此语句的示例可以在 Identifying the Top Three Extreme Values with the Output Statistics
中找到让我们稍微扩展一下示例数据;
data myInput;
infile datalines dsd delimiter='09'x;
input
@1 ID 1.
@4 Val .
@7 Date yymmdd10.;
format Date yymmdd10.;
datalines;
2 X 2009-10-01
2 X 2009-10-02
2 Z 2009-10-03
3 C 2010-10-01
3 B 2010-10-03
3 A 2010-10-04
3 A 2010-12-01
3 B 2010-12-03
3 C 2010-12-04
;
run;
现在让我们计算每个“ID”的每个“Val”的频率和最后一次出现;
proc sql;
create view myView as
select ID, Val, max(Date) as Date format=yymmdd10., count(*) as freq
from myInput
group by ID, Val;
run;
最后,为每个 ID 保留一个 Val,优先选择出现频率高的那个,在出现频率相同的情况下选择最近的那个;
proc means data=myView nway noprint;
class ID;
output out=myModes(keep= ID Mode)
idgroup( max(freq Date) out[1] (Val)=Mode);
run;
proc print data=myModes;
run;
结果是;
ID Mode
2 X
3 C
这是我想出的 proc sql 解决方案,尽管我更喜欢所选的解决方案:
%macro modes(data, mode , tie , break, outset , lib );
proc sql;
create table &lib..&outset as
select &id, &mode
from (select &id, &mode, latest
from(select &id, &mode, latest
from(select &id, &mode, count(*) as n, &break.(&tie) as latest
from &data
where &mode is not null
group by &id, &mode)
group by &id
having n = max(n))
group by &id
having latest= &break.(latest) )
;
quit;
%mend modes;
%modes(data=mydata, mode=age , tie=somedateorvalue , break=max, outset=outtable , lib =mylib);
- Tie : 是用来打破平局的列
- break :如果您希望最早或最晚日期或高值或低值与 断开联系,则应为最小值或最大值
其余的应该是不言自明的。