SAS DO Loop, кажется, пропускает записи
При написании очень простого шага DATA, чтобы начать новый проект, я столкнулся с некоторым странным поведением.
Единственное различие между set1 и set2 состоит в использовании переменной lagscore в уравнении в set1 против dummy в уравнении в set2.
set1 производит вывод, который, по-видимому, указывает на то, что включение lagscore приводит к тому, что переменные Score и Lagscore будут неопределенными в половине итераций.
Обратите внимание, что я был осторожен, чтобы НЕ вызывать lag() более одного раза, и я включаю вызов в set2 просто для того, чтобы убедиться, что вызов функции lag() не является источником проблемы.
Я ценю любые объяснения. Я довольно долго отсутствовал в SAS и чувствую, что упускаю что-то фундаментальное в том, как происходит обработка.
(Извините за трудный для чтения вывод. Я не мог понять, как вставить его и сохранить интервал)
data set1;
obs=1;
score=500;
a_dist = -5.0;
b_dist = 0.1;
dummy = 0;
output;
do obs = 2 to 10;
lagscore = lag(score);
score = lagscore + 1 /(b_dist * lagscore + a_dist);
output;
end;
run;
data set2;
obs=1;
score=500;
a_dist = -5.0;
b_dist = 0.1;
dummy = 0;
output;
do obs = 2 to 10;
lagscore = lag(score);
/* score = lagscore + 1 /(b_dist * lagscore + a_dist);*/
score = dummy + 1 /(b_dist * dummy + a_dist);
output;
end;
run;`
Set1 результаты
obs score a_dist b_dist dummy lagscore
1 500 -5 0.1 0 .
2 . -5 0.1 0 .
3 500.02 -5 0.1 0 500
4 . -5 0.1 0 .
5 500.04 -5 0.1 0 500.02
6 . -5 0.1 0 .
7 500.06 -5 0.1 0 500.04
8 . -5 0.1 0 .
9 500.08 -5 0.1 0 500.06
10 . -5 0.1 0 .
Set2 результаты
obs score a_dist b_dist dummy lagscore
1 500 -5 0.1 0 .
2 -0.2 -5 0.1 0 .
3 -0.2 -5 0.1 0 500
4 -0.2 -5 0.1 0 -0.2
5 -0.2 -5 0.1 0 -0.2
6 -0.2 -5 0.1 0 -0.2
7 -0.2 -5 0.1 0 -0.2
8 -0.2 -5 0.1 0 -0.2
9 -0.2 -5 0.1 0 -0.2
10 -0.2 -5 0.1 0 -0.2
1 ответ
Ключевым моментом является то, что когда вы вызываете функцию lag(), она возвращает значение из очереди, которая инициализируется пропущенными значениями. По умолчанию это очередь с одним элементом.
В вашем коде:
score=500 ;
*...;
do obs = 2 to 10;
lagscore = lag(score);
score = lagscore + 1 /(b_dist * lagscore + a_dist);
output;
end;
На первой итерации цикла (obs=2) LAGSCORE будет назначено пропущенное значение, поскольку очередь инициализируется пропущенным значением. Значение 500 будет сохранено в очереди. SCORE будет присвоено пропущенное значение, потому что отсутствует LAGSCORE, и, следовательно, выражение lagscore + 1 /(b_dist * lagscore + a_dist)
вернется пропавшим без вести.
На второй итерации цикла (obs=3) LAGSCORE будет присвоено значение 500 (чтение из очереди), а значение SCORE (отсутствующее значение) будет записано в очередь. Затем баллу присваивается значение 500,2 из выражения lagscore + 1 /(b_dist * lagscore + a_dist)
,
На третьей итерации цикла (obs=4) LAGSCORE будет присвоено пропущенное значение (считанное из очереди), а значение 500.2 будет записано в очередь.
И этот шаблон повторяется.
Если я понимаю ваше намерение, вам на самом деле не нужна функция LAG для такого рода создания данных. Вы можете просто использовать DO
Цикл с оператором вывода в нем и обновлять значение SCORE после вывода каждой записи. Что-то вроде:
data set1 ;
score = 500 ;
a_dist = -5.0 ;
b_dist = 0.1 ;
do obs = 1 to 10 ;
output ;
score = score + (1 /(b_dist * score + a_dist)) ;
end ;
run ;
Возвращает:
score a_dist b_dist obs
500.000 -5 0.1 1
500.022 -5 0.1 2
500.044 -5 0.1 3
500.067 -5 0.1 4
500.089 -5 0.1 5
500.111 -5 0.1 6
500.133 -5 0.1 7
500.156 -5 0.1 8
500.178 -5 0.1 9
500.200 -5 0.1 10