【问题标题】:Is there a way to return the specific row number on SAS?有没有办法在 SAS 上返回特定的行号?
【发布时间】:2013-10-29 06:11:41
【问题描述】:

这是数据集的一部分:

   Obs Buffer
     ...
    75 14
    76 13 
    77 64 
    78 38.1% 
    79 29.2% 
    80 69.2% 
    81 33 
    82 5-12
     ... 

我只需要包含“%”的数据和前面的两行。比如这种情况下我要拉出“13”“64”“38.1%”“29.2%”和“69.2%”。

有什么方法可以实现吗?

【问题讨论】:

    标签: sas dataset


    【解决方案1】:

    回答您的问题:_N_ 变量将返回数据步骤循环通过数据语句的次数。 (http://support.sas.com/documentation/cdl/en/lrcon/62955/HTML/default/viewer.htm#a000695104.htm)

    但是,要解决您的问题,请使用 lag() (http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212547.htm) 和包含语句,例如

    data justBuffers;
        set yourDS;
        twoBefore = lag2(Buffer);
        oneBefore = lag1(Buffer);
        if Buffer ? '%' then do;
            if not missing(twoBefore) then do;
                x = twoBefore;
                output;
            end;
            if not missing(oneBefore) then do;
                x = oneBefore;
                output;
            end;
            x = Buffer;
            output;
            call missing(oneBefore, twoBefore);
        end;
        keep x;
    run;
    

    我没有测试过代码,所以要小心!我相信你可以让它更流畅。

    【讨论】:

      【解决方案2】:

      我喜欢使用point 来处理这类事情。 _N_ 作为行计数器是可靠的,只要您没有对数据步骤循环做任何有趣的事情。

      data have;
      length buffer $50;
      input obs buffer $;
      datalines;
      75 14
      76 13 
      77 64 
      78 38.1% 
      79 29.2% 
      80 69.2% 
      81 33 
      82 5-12
      ;;;;
      run;
      data want;
      set have;
      pointer=_N_;
      if find(buffer,'%') then do;
        output;
        pointer=_N_-1;
        set have point=pointer;
        if not (find(buffer,'%')) then do;
          output;
          pointer=_N_-2;
          set have point=pointer;
          if not (find(buffer,'%')) then output;
        end; 
      end;
      run;
      

      如果您需要恢复您的订单,您可以在之后按pointer 排序(或obs,如果这是一个真正的变量 - 我认为它不是)。如果obs 确实是一个真正的变量(或者如果你用视图使它成为现实),那么 SQL 中有一种有趣的方法可以做到这一点:

      proc sql;
      create table want as
          select H.* from have H 
              left join have V on H.obs=V.obs-1
              left join have A on H.obs=A.obs-2
              where 
                  (find(H.buffer,'%'))
                  or
                  (find(V.buffer,'%'))
                  or
                  (find(A.buffer,'%'))
              order by H.obs
              ;
      quit;
      

      如何在没有数据传递的情况下使 obs 真实:

      data have_vw/view=have_vw;
      set have;
      obs=_n_;
      run;
      

      然后在 SQL 查询中使用have_vw 而不是have(在所有三个位置)。

      【讨论】:

      • 附带说明,您可以使用预读合并 (merge have (in=a) have (in=b firstobs=2) have(in=c firstobs=3)) 在常规 SAS 中复制 SQL 连接解决方​​案,如果这能让您满意的话。 SQL 解决方案更短,所以我更喜欢,但没有那么不同。
      【解决方案3】:

      按照kungfujam的思路,我得到了下面的代码,它可以工作了。

      data adjust;
      set source;
      oneBefore = lag1(Buffer);
      twoBefore = lag2(Buffer);
      threeBefore = lag3(Buffer);
      fourBefore = lag4(Buffer);
      if index(buffer,'%')^=0 and index(onebefore,'%')^=0 and index(twobefore,'%')^=0then do;
              x = fourBefore;
              output;
              x = threeBefore;
              output;
              x = twoBefore;
              output;
              x = oneBefore;
              output;
              x=buffer;
             output;
          end;
        keep x;
      run;
      

      【讨论】:

        猜你喜欢
        • 2021-12-10
        • 1970-01-01
        • 2020-03-20
        • 1970-01-01
        • 1970-01-01
        • 2017-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多