Заключенные в скобки функции% SYSFUNC () выдают ошибку при обнаружении скобок - PullRequest
1 голос
/ 09 марта 2019

Мне нужно написать макропрограмму для генерации списка для вычисления скользящего среднего, где мне понадобится построить несколько строк следующим образом:

var1_ma_past_1=mean(var1, lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1));
var1_ma_past_2=mean(lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1));
var1_ma_past_3=mean(lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1), lag7(var1));
[...]
var2_ma_past_1=mean(var2, lag1(var2), lag2(var2), lag3(var2), lag4(var2), lag5(var2));

моя программа-пример

%macro test ;
    %do i = 1 %to 5;
    %let ln&i = ;
        %do j = 1 %to 5;
            %let dml = %str(,);
            %let pos = %str(lag&i(var&j));
            %let ln&j = %sysfunc(catx(&dml, &&ln&j, &pos));
        %end;
    %end;
    /* example output */
    %put &ln1;
%mend test;
%test

&j хотя начальные и конечные значения планируется заменить параметрами.

выход желателен для &ln1

lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)

но для &ln2 &ln3 и т. Д. Это не так (lag1(varn) отсутствует)

lag2(var4),lag3(var4),lag4(var4),lag5(var4)
lag2(var3),lag3(var3),lag4(var3),lag5(var3)

Кроме того, я получил вывод лога флудинга, говорящий ERROR: Required operator not found in expression:, что связано с круглыми скобками внутри cats(), который находится внутри %sysfunc(), пример макроса для репликации это

%macro test2;
    %let x=meow;
    %put %sysfunc(cats(x,lag()));
%mend;
%test2

Я пытался замаскировать скобки с помощью %str, %superq, %bquote, но ни одна из них не сработала.

Я бы хотел выучить

  1. причина неправильного вывода для &ln2, &ln3 и т. Д.
  2. причина ERROR: Required operator not found in expression: и способы ее устранения (или обходной путь, или даже подавление ошибки, если она не критична)

Заранее спасибо.

1 Ответ

1 голос
/ 09 марта 2019

Нет необходимости использовать функции CAT ... () в коде макроса.

В коде макроса для объединения значений вы просто расширяете их рядом друг с другом.Также похоже, что ваша логика смешивает счетчики I и J.

%macro test ;
%do i = 1 %to 5;
  %let list = ;
  %let dlm = ;
  %do j = 1 %to 5;
    %let list = &list.&dlm.lag&j(var&i) ;
    %let dlm = ,;
  %end;
  %put &=i &=list;
%end;
%mend test;
%test

Результаты:

I=1 LIST=lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)
I=2 LIST=lag1(var2),lag2(var2),lag3(var2),lag4(var2),lag5(var2)
I=3 LIST=lag1(var3),lag2(var3),lag3(var3),lag4(var3),lag5(var3)
I=4 LIST=lag1(var4),lag2(var4),lag3(var4),lag4(var4),lag5(var4)
I=5 LIST=lag1(var5),lag2(var5),lag3(var5),lag4(var5),lag5(var5)

Для вашей реальной проблемы вы можете создать макрос, который возвращает толькоСписок с разделителями-запятыми в результате вызова макроса.

%macro lags(varname,first,last);
%local lag dlm;
%do lag= &first %to &last ;
  %if (&lag > 0) %then %*;&dlm.lag&lag(&varname);
  %else %*;&dlm.&varname;
  %let dlm=,;
%end;
%mend lags;

%put var1_ma_past_1=mean(%lags(var1,0,5));
%put var1_ma_past_2=mean(%lags(var1,1,6));
%put var1_ma_past_3=mean(%lags(var1,2,7));
%put var2_ma_past_1=mean(%lags(var2,0,5));

Почему вы получаете эти сообщения об ошибках:

Функция макроса %sysfunc() должна попытатьсявыяснить, является ли каждый аргумент символьным или числовым для такой функции, как CATX(), которая может работать с любым типом ввода.Вот почему () в значениях аргумента сбивает его с толку, поскольку похоже, что вы пытаетесь передать числовое выражение.

18    %put %sysfunc(catx(|,a(b),b));
ERROR: Required operator not found in expression: a(b)
a(b)|B
19    %put %sysfunc(catx(|,(1+2),b));
3|B

Вы можете заключить в кавычки значения и затем удалить их позже (если ваши значения не содержат кавычек).

%let left=A(b);
%let right=b;
%let intermediate=%sysfunc(catx(|,"&left","&right"));
%let want=%sysfunc(compress(&intermediate,%str(%"));
%put &=want;
...