我有一个像这样的数据集
OBS | foo |吧|更
1 | 111 | 11 | 9 2 | 9 | 2 | 2 ........
我需要扔掉4个最大和4个最小的foo(之后我会用bar做类似的事情)基本上要继续但是我不确定最有效的方法。我知道有最小和最大的函数,但我不明白如何使用它们从已经制作的数据集中获取最小的4或最大的4。我猜或者我可以删除最小和最大4次,但这听起来不必要的单调/耗时。还有更好的方法吗?
答案 0 :(得分:2)
PROC RANK很容易为你做这件事。如果你知道观察的总数,那就太微不足道了 - 如果你不这样做,那就更难了。
proc rank data=sashelp.class out=class_ranks(where=(height_r>4 and weight_r>4));
ranks height_r weight_r;
var height weight;
run;
例如,去除了4个最小高度或重量的观察值。最大的4需要知道最高等级,或者做第二个处理步骤。
data class_final;
set class_ranks nobs=nobs;
if height_r lt (nobs-3) and weight_r lt (nobs-3);
run;
当然,如果你只是删除这些值,那么在数据步骤中完成所有操作,如果符合条件,则call missing
变量,而不是删除观察值。
答案 1 :(得分:1)
您需要在数据集中至少进行2次传递,但是要执行此操作 - 一个用于查找顶部和底部4的值,以及一个用于排除这些观察值。
您可以使用proc univariate获取顶部和底部的5个值,然后使用其中的输出为后续数据步骤创建where过滤器。这是一个例子:
ods _all_ close;
ods output extremeobs = extremeobs;
proc univariate data = sashelp.cars;
var MSRP INVOICE;
run;
ods listing;
data _null_;
do _N_ = 1 by 1 until (last.varname);
set extremeobs;
by varname notsorted;
if _n_ = 2 then call symput(cats(varname,'_top4'),high);
if _n_ = 4 then call symput(cats(varname,'_bottom4'),low);
end;
run;
data cars_filtered;
set sashelp.cars(where = ( &MSRP_BOTTOM4 < MSRP < &MSRP_TOP4
and &INVOICE_BOTTOM4 < INVOICE < &INVOICE_TOP4
)
);
run;
如果有多个观察结果与第四大/最小相关,则会过滤掉所有观察结果。
答案 2 :(得分:0)
您可以使用proc sql将foo的不同值的数量放入宏var(包括null值作为distinct)。
在您的数据步骤中,您可以使用first.foo和宏变量来选择性地仅输出那些没有最小值或最大值4的值。
proc sql noprint;
select count(distinct foo) + count(distinct case when foo is null then 1 end)
into :distinct_obs from have;
quit;
proc sort data = have; by foo; run;
data want;
set have;
by foo;
if first.foo then count+1;
if 4 < count < (&distinct_obs. - 3) then output;
drop count;
run;
答案 3 :(得分:0)
我还找到了一种方法,它似乎与IML一起工作(我通过尝试以不同方式重做事物来练习)。我知道我观察到的最大数量,并且已经按照感兴趣的变量的顺序对其进行了排序。
PROC IML;
EDIT data_set;
DELETE point {{1, 2, 3, 4,51, 52, 53, 54};
PURGE;
close data_set;
run;
我没有使用IML,但在阅读文档时我偶然发现了这一点。感谢所有回答我问题的人!