2014-09-04 2 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 (группа).
  3. Запустите другой шаг данных и проверьте, не имеет ли значение из (2) - (1) меньше 5. Если это так, присвойте переменной _num_to_sum_ (например) значение, которое вы хотите суммировать, в противном случае оставьте его пустым или присвойте 0.
  4. и последний сделайте шаг sql с sum (_num_to_sum_) и сгруппируйте результаты, группируя переменную из (1).

EDIT: Я добавил живой пример концепции в немного более уплотняется способом.

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

+0

Активировать мой ответ тогда было бы хорошо =) – kaytrance

+0

Это требует 15 rep: D Sry Я новичок. И btw я не мог выполнить ваше решение. Я мог бы найти правильную переменную агрегации sql, если _n_ делится на 5, тогда count + 1, например, так легко. Я хотел бы сделать это с помощью нескольких массивов, сохранить или установить команды, если возможно – criticalth

0

Вы можете сделать это на шаге данных или используя PROC EXPAND от SAS/ETS, если таковые имеются.

Для шага данных идея состоит в том, что вы начинаете с суммарной суммы (summ), но отслеживаете количество значений, которые были добавлены до сих пор (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 расшириться, в которой это действительно только одна линия. Мы просто скажем, чтобы вычислить обратную перемещающуюся сумму в окне ширины 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 expand. Хотя это только пример. Я намерен выполнить очень сложный расчет с учетом последних «n» наблюдений, и мне было интересно, есть ли способ сделать это, не отставая от разных переменных n раз. Если у вас есть дополнительные предложения, поделитесь ими. Спасибо :) – criticalth

+0

Можем ли мы как-то решить проблему, используя цикл DOW? – criticalth

+0

Я не знаю, что такое цикл DOW, но я добавил еще одно решение, которое позволяет произвольно вычислять последние «n» наблюдения. – Aniko

Смежные вопросы