摆脱SAS中数据集的第k个最小值和最大值

时间:2015-05-27 18:17:39

标签: dataset sas

我有一个像这样的数据集

OBS | foo |吧|更

1 | 111 | 11 | 9 2 | 9 | 2 | 2 ........

我需要扔掉4个最大和4个最小的foo(之后我会用bar做类似的事情)基本上要继续但是我不确定最有效的方法。我知道有最小和最大的函数,但我不明白如何使用它们从已经制作的数据集中获取最小的4或最大的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,但在阅读文档时我偶然发现了这一点。感谢所有回答我问题的人!