2014-12-30 16 views
0

Предположим, что набор данных имеет 3 колонкиКак использовать функцию задержки для вычисления следующего наблюдения в SAS

Obs Theo Cal 
1 20 20 
2 21 23 
3 21 .  
4 22 .  
5 21 .  
6 23 .  

Theo является теоретическое значение, а Cal является оценочная стоимость.

Мне нужно рассчитать недостающие Cal. Для каждого Obs его Cal представляет собой линейную комбинацию из двух предыдущих значений Cal.

Cal(3) = Cal(2) * &coef1 + Cal(1) * &coef2.
Cal(4) = Cal(3) * &coef1 + Cal(2) * &coef2.

Но Cal = lag1(Cal) * &coef1 + lag2(Cal) * &coef2 не работал, как я и ожидал.

+1

Я провел аналогичную симуляцию, и это сработало для меня. Вы можете уточнить? Как и где вы определили 'coef1' и' coef2'? Какой результат вы получаете? Предоставление воспроизводимого примера также поможет решить вашу проблему. – Vincent

+0

@ Vincent coef - две глобальные макропеременные. например. '% let coef1 = 0.38'. lag1() и lag2() возвращают отсутствующие значения. – Lovnlust

+0

Код должен работать нормально. Являются ли ваши расчеты задержки в IF или другом условном блоке? Если да, это будет проблемой. Вы можете использовать условный лаг для Google, чтобы объяснить, почему это не работает. – Reeza

ответ

3

Проблема с использованием запаздывания - это когда вы используете lag1 (Cal), вы не получаете последнее значение Cal, которое было записано в выходной набор данных, вы получаете последнее значение, которое было передано функции lag1. Вероятно, было бы проще использовать сохранить следующим образом:

data want(drop=Cal_l:); 
    set have; 
    retain Cal_l1 Cal_l2; 

    if missing(Cal) then Cal = Cal_l1 * &coef1 + Cal_l2 * &coef2; 

    Cal_l2 = Cal_l1; 
    Cal_l1 = Cal; 
run; 
+1

Я не совсем уверен, что понимаю, почему вы сочетаете сохранение и отставание здесь :) Ничего изначально не так с ним, просто сбивает с толку. – Joe

+0

Да, вы правы ... Мне просто хотелось добавить его, потому что вопрос был о задержке. На самом деле это менее эффективно. Раньше у меня это было как Cal_l2 = Cal_l1. Я изменю его. – Leo

0

Там может быть способом сделать это в DATA шаге, но, как для меня, когда я хочу SAS обрабатывать итеративно, я использую PROC IML и do петли. Я назвал таблицу SO и успешно провел следующее:

PROC IML; 

    use SO;   /* create a matrix from your table to be used in proc iml */ 
    read all var _all_ into table; 
    close SO; 

    Cal=table[,3]; 

    do i=3 to nrow(cal);    /* process iteratively the calculations */ 

     if cal[i]=. then do;cal[i]=&coef1.*cal[i-1]+&coef2.*cal[i-2]; 
     end;else do;end; 
    end; 

    table[,3]=cal; 
    Varnames={"Obs" "Theo" "Cal"}; 

    create SO_ok from table [colname=varnames];  /* outputs a new table */ 
    append from table; 
    close SO_ok; 
QUIT; 

Я не говорю, что вы не можете использовать lag() и DATA шаг, чтобы добиться того, что вы хотите сделать. Но я считаю, что PROC IML полезен и интуитивно понятен, когда дело касается итеративного процесса.

+0

Первое предложение неверно. LAG (как и все остальное на шаге данных SAS), безусловно, обрабатывает строку за строкой. – Joe

+0

Спасибо @ Винсент. Но у меня нет 'proc iml' на этом ПК .. – Lovnlust

1

Я бы предположил, что вы написали datastep вроде так.

data want; 
    set have; 
    if missing(cal) then 
    cal = lag1(cal)*&coef1 + lag2(cal)*&coef2; 
run; 

LAG не захватывая предыдущее значение, а скорее создает очереди, которая является N долго и дает вам конечную часть. Если у вас есть это утверждение IF, то вы никогда не поместите полезные значения CAL в эту очередь - вы будете только бросать в нее пропуски. Смотрите его так:

data have; 
    do x=1 to 10; 
    output; 
    end; 
run; 

data want; 
    set have; 
    real_lagx = lag(x); 
    if mod(x,2)=0 then do; 
    not_lagx = lag(x); 
    put real_lagx= not_lagx=; 
    end; 
run; 

Реальный лагов являются немедленным последнее значение, в то время как NOT лаги последнее значение даже, потому что они внутри IF.

У вас есть два основных варианта. Используйте RETAIN для отслеживания последних двух наблюдений или используйте LAG, как я сделал выше, перед оператором IF, а затем используйте значения с задержкой внутри оператора IF. С любым методом нет ничего лучше или хуже; LAG работает так, как вы это хорошо понимаете. RETAIN часто считается «более безопасным», потому что его сложнее ввернуть; вам также легче посмотреть, что вы делаете.

data want; 
    set have; 
    retain cal1 cal2; 
    if missing(cal) then cal=cal1*&coef1+cal2*&coef2; 
    output; 
    cal2=cal1; 
    cal1=cal; 
run; 

или

data want; 
    set have; 
    cal1=lag1(cal); 
    cal2=lag2(cal); 
    if missing(cal) then cal=cal1*&coef1+cal2*&coef2; 
run; 

Последний метод будет работать только если cal нечасто хватает - особенно, если он никогда не хватает больше, чем один раз из любых трех наблюдений.В первом примере будет заполнено первое cal (строка 3), но оттуда оно всегда будет отсутствовать. Это может быть или не быть желательным; если это не так, используйте retain.

+0

Я не думаю, что последний пример будет работать, потому что с функциями задержки вы только подбираете значения cal из набора данных «have», которые отсутствуют, а не cal, которые вы создали в «if missing ...» " заявление. Таким образом, вы просто получите отсутствующие значения в наборе данных «хотите». – Leo

+0

Aaaand мы помним, почему я обычно не использую лаг. Благодарю. – Joe

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