2014-09-04 79 views
1

我如何执行数据集中最后n个观测值的计算 例如,如果我有10个观测值,我想创建一个变量来总结最后5个值另一个变量。请不要暗示我滞后5次或使用模块(N)。我需要一个比这更优雅的解决方案。我如何执行最后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; 

非常感谢您!

回答

0

在任何情况下读取该:) 我解决它,我需要它要解决的途径。尽管现在我更加好奇两个(保留和我的解决方案)中的哪一个在计算/处理时间方面更为优化。

这里是我的解决方案:

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; 
0

我可以提供比较难看溶液:

  1. 运行数据的步骤加入越来越多到每个
  2. 运行sql步骤并添加max(group)的列。
  3. 运行另一个数据步骤,并检查(2) - (1)中的值是否小于5.如果是,则分配给_num_to_sum_变量(例如)要合计的值,否则将其留空或分配0.
  4. 并且最后执行一个sql步骤sum(_num_to_sum_)并通过对来自(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; 
+0

Thnaks,每一个岗位是appriciated。它并不那么难看。我喜欢;] – criticalth 2014-09-04 11:52:30

+0

Upvoting我的答案然后会很好=) – kaytrance 2014-09-04 12:06:52

+0

它需要15代表:D Sry我是新的。顺便说一句,我无法执行您的解决方案。我可以找到一个合适的sql聚合变量,如果_n_可以被5整除然后计数+ 1,那么这样做很容易。我想用几个数组来做,保留或设置命令如果可能 – criticalth 2014-09-04 12:46:12

0

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

对于数据步骤的想法是,您从累计和(summ)开始,但记录到目前为止添加的值的数量(ninsum)。一旦达到5,就开始输出累计和到目标变量(juliet),并从下一步开始减去滞后5值,仅存储最后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扩大,其中这真的只是一条线。我们只是告诉它在宽度为5的窗口中计算向后移动的总和,并将前4个观察值设置为缺失(默认情况下,它会将您的序列在左侧扩展0)。

proc expand data=alpha out=gamma; 
     convert lima = juliet /transformout=(movsum 5 trimleft 4); 
run; 

proc print data=gamma; 
run; 

编辑

如果你想要做更复杂的计算,你需要携带在保留变量之前的值。我以为你想避免这种情况,但在这里它是:

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; 
+0

确实非常有用。我不知道proc扩展的功能。尽管这只是一个例子。我打算在考虑到最后的“n”个观测值的情况下进行非常复杂的计算,并且我想知道是否有办法做到这一点,而不会在n次滞后不同变量。如果您有任何其他建议,请分享。谢谢:) – criticalth 2014-09-08 16:30:33

+0

我们能以某种方式解决使用DOW循环的问题吗? – criticalth 2014-09-12 09:05:11

+0

我不知道DOW循环是什么,但我添加了另一个解决方案,可以对最后的“n”个观察值进行任意计算。 – Aniko 2014-09-12 13:56:02