Sas 如何计算最后n个观测值

Sas 如何计算最后n个观测值,sas,Sas,如何计算数据集中的最后n个观测值 例如,如果我有10个观察值,我想创建一个变量,将另一个变量的最后5个值相加。请不要建议我延迟5次或使用模块(N)。我需要一个更优雅的解决方案 下面的代码alpha是我拥有的数据集,bravo是我需要的数据集 data alpha; input lima @@ ; cards ; 3 1 4 21 3 3 2 4 2 5 ; run ; data bravo; input lima juliet; cards; 3 . 1 . 4 . 21

如何计算数据集中的最后n个观测值 例如,如果我有10个观察值,我想创建一个变量,将另一个变量的最后5个值相加。请不要建议我延迟5次或使用模块(N)。我需要一个更优雅的解决方案

下面的代码alpha是我拥有的数据集,bravo是我需要的数据集

data alpha; 
    input lima @@ ;
    cards ;
3 1 4 21 3 3 2 4 2 5
; 
run ;

data bravo;
input lima juliet;
cards;
3 .
1 .
4 .
21 .
3 32
3 32
2 33
4 33
2 14
5 16
;
run;

提前谢谢你

我可以提供相当丑陋的解决方案:

data bravo(keep = var1 summ);
    set alpha;
    do i=_n_ to _n_-4 by -1;
        set alpha(rename=var1=var2) point=i;
        summ=sum(summ,var2);        
    end;
run;
  • 运行数据步骤并向每个组添加递增的数字
  • 运行sql步骤并添加max(group)
  • 运行另一个数据步骤,检查(2)-(1)中的值是否小于5。如果是,请将要求和的值(例如)赋给\u num\u to\u sum\u变量,否则留空或赋0
  • 最后用sum(\u num\u to\u sum\u)执行一个sql步骤,并通过将(1)中的变量分组对结果进行分组
  • 编辑:我以更紧凑的方式添加了该概念的一个实例

    input var1 $ var2;
    cards;
    aaa 3
    aaa 5
    aaa 7
    aaa 1
    aaa 11
    aaa 8
    aaa 6
    bbb 3
    bbb 2
    bbb 4
    bbb 6
    ;
    run;
    
    data step1;
        set sourcetable;
        by var1;
        retain obs 0;
        if first.var1 then obs = 0;
        else obs = obs+1;
        if obs >=5 then to_sum = var2;
    run;
    
    proc sql;
        create table rezults as
            select distinct var1, sum(to_sum) as needed_summs
            from step1
            group by var1;
    quit;
    

    您可以在数据步骤中执行此操作,也可以使用SAS/ETS中的PROC EXPAND(如果可用)

    对于数据步骤,您可以从累积和开始(
    sum
    ),但要跟踪到目前为止添加的值的数量(
    ninsum
    )。一旦达到5,就开始将累积和输出到目标变量(
    juliet
    ),然后从下一步开始减去滞后的-5值,以仅存储最后五个值的和

    data beta;
        set alpha;
        retain summ ninsum 0;
    
        summ + lima;
        ninsum + 1;
        l5 = lag5(lima);
    
        if ninsum = 6 then do;
            summ = summ - l5;
            ninsum = ninsum - 1;
        end;
    
        if ninsum = 5 then do;
            juliet = summ;
        end;
    
    run;
    
    proc print data=beta;
    run;
    
    然而,有一个过程可以进行所有类型的累积、移动窗口等计算:PROC EXPAND,其中实际上只有一行。我们只是告诉它在一个宽度为5的窗口中计算向后移动的和,并将前4个观察值设置为missing(默认情况下,它将在左侧将序列扩展0)

    编辑

    如果要进行更复杂的计算,则需要在保留变量中携带以前的值。我以为你想避免这样,但事实是:

    data epsilon;
        set alpha;
        array lags {5};
        retain lags1 - lags5;
    
        /* do whatever calculation is needed */
        juliet = 0;
        do i=1 to 5;
            juliet = juliet + lags{i};
        end;
    
        output;
    
        /* shift over lagged values, and add self at the beginning */
        do i=5 to 2 by -1;
            lags{i} = lags{i-1};
        end;
        lags{1} = lima;
    
        drop i;
    run;
    
    proc print data=epsilon;
    run;
    

    如果有人读到这篇文章:) 我以我需要的方式解决了它。虽然现在我更好奇的是,在计算/处理时间方面,这两个(保留和我的解决方案)中哪一个更为优化

    以下是我的解决方案:

    data bravo(keep = var1 summ);
        set alpha;
        do i=_n_ to _n_-4 by -1;
            set alpha(rename=var1=var2) point=i;
            summ=sum(summ,var2);        
        end;
    run;
    

    好的,每一个帖子都是被推荐的。而且也没那么难看。我喜欢它;]向上投票我的答案会很好=)这需要15个代表:我是新来的。顺便说一句,我无法执行您的解决方案。我可以找到一个合适的sql聚合变量,如果n可以被5整除,那么计数+1,例如,这样做比较容易。如果可能的话,我想用一些数组,保留或设置命令。请看我对初始答案的补充,希望能有所帮助。这根本不是问题所在。我需要最后5次保存的总和。新变量中的每条记录都应包含旧变量最近5次观察的总和,因为数据集中没有用于分组的变量。设想一个数据集有一列所有数字。您必须创建第二列,其中缺少前4个OB,因为没有5个观察值需要求和。对于第2列的第5次观察,该值应该是最后5次观察的总和,第6次观察,第2列应该是第1列的第6次第5次第4次第3次第2次观察的总和,等等。非常有用。我不知道proc expand的功能。尽管这只是一个例子。考虑到最后的“n”个观测值,我打算执行非常复杂的计算,我想知道是否有一种方法可以做到这一点,而不会使不同的变量滞后n次。如果您有任何其他建议,请分享。谢谢:)我不知道道指循环是什么,但我添加了另一个解决方案,允许对最后的“n”个观测值进行任意计算。非常感谢你的所有帖子:)我想我将使用滞后。它最适合我正在尝试做的事情:)