#sas
#sas
Вопрос:
Я хочу сохранить экземпляр переменной шага данных в макропеременной с помощью вызова symput, затем использовать эту макропеременную на том же шаге данных для заполнения нового поля, присваивая ему новое значение каждые 36 записей.
Я попробовал следующий код:
data a;
set a;
if MOB = 1 then do;
MOB1_accounts = accounts;
call symput('MOB1_acct', MOB1_accounts);
end;
else if MOB > 1 then MOB1_accounts = amp;MOB1_acct.;
run;
У меня есть серия повторяющихся мобов (1-36). Я хочу создать поле с именем MOB1_Accts, установить его равным количеству учетных записей для этой когорты, где MOB = 1, и сохранить это значение, когда MOB = 2, 3, 4 и т.д. По сути, я хочу «перетаскивать» значение MOB 1 каждые 36 записей.
По какой-то причине эта макропеременная возвращает «1» вместо правильного # accounts. Я думаю, что это может быть проблема с символами / числами, но я не уверен. Я перепробовал все возможные перестановки одинарных кавычек, двойных кавычек, символов и т.д… не повезло.
Спасибо за помощь!
Ответ №1:
Вы неправильно используете макросистему.
Вводящий элемент ampersand ( amp;
) в исходном коде сообщает SAS разрешить следующий символ и поместить его в поток отправки кода. Таким образом, разрешенные данные amp;MOB1_acct.
не могут быть изменены на этапе выполнения ДАННЫХ. Другими словами, выполняемый шаг не может изменить свой исходный код — разрешенная макропеременная будет одинаковой для всех неявных итераций шага, поскольку ее значение стало частью исходного кода шага.
Вы можете использовать SYMPUT()
SYMGET()
функции и для перемещения строк из шага ДАННЫХ в шаг ДАННЫХ и обратно. Но это все равно неправильный подход к вашей проблеме.
Наиболее простой метод может быть
- использование
retain
переменной ed mod (_n_, 36)
вычисление для определения каждой 36-й строки. (_n_
является прокси для номера строки на простом шаге с одним набором.)
Пример:
data a;
set a;
retain mob1_accounts;
* every 36 rows change the value, otherwise the value is retained;
if mod(_n_,36) = 1 then mob1_accounts = accounts;
run;
Вы не показали никаких данных, поэтому фактические инструкции программы, которые вам нужны, могут немного отличаться.
В отличие SYMPUT/SYMGET
от RETAIN
Как указано, SYMPUT/SYMGET
это возможный способ сохранить значения, отключив их сохранение в таблице символов макросов. Однако существует штраф. Для SYM*
сохранения / извлечения символьного значения и, возможно, дополнительных преобразований между символьным и числовым требуется вызов функции и любые манипуляции / черные ящики.
Пример:
1 000 000 прочитанных строк. DATA _null_
шаги, позволяющие избежать записи накладных расходов как части контраста.
data have;
do rownum = 1 to 1e6;
mob 1;
accounts = sum(accounts, rand('integer', 1,50) - 10);
if mob > 36 then mob = 1;
output;
end;
run;
data _null_;
set have;
if mob = 1 then call symput ('mob1_accounts', cats(accounts));
mob1_accounts = symgetn('mob1_accounts');
run;
data _null_;
set have;
retain mob1_accounts;
if mob = 1 then mob1_accounts = accounts;
run;
В моих системных журналах
142 data _null_;
143 set have;
144
145 if mob = 1 then call symput ('mob1_accounts', cats(accounts));
146
147 mob1_accounts = symgetn('mob1_accounts');
148 run;
NOTE: There were 1000000 observations read from the data set WORK.HAVE.
NOTE: DATA statement used (Total process time):
real time 0.34 seconds
cpu time 0.34 seconds
149
150 data _null_;
151 set have;
152 retain mob1_accounts;
153
154 if mob = 1 then mob1_accounts = accounts;
155 run;
NOTE: There were 1000000 observations read from the data set WORK.HAVE.
NOTE: DATA statement used (Total process time):
real time 0.04 seconds
cpu time 0.03 seconds
Или
way real cpu
------------- ------ ----
SYMPUT/SYMGET 0.34 0.34
RETAIN 0.04 0.03
Комментарии:
1. По какой-то причине мой вызов symput symget/symgetn по-прежнему возвращает только «1». Но оператор retain работал отлично. Я не знаю, как я не слышал об этом до сих пор — большое спасибо!