SAS宏变量更改+数组索引

发布于 2024-10-28 04:27:41 字数 771 浏览 2 评论 0原文

这与以下问题相关:SAS宏变量更改

下面的代码解释了这个问题:

%macro test (arg=); 
    options  mlogic mprint symbolgen;
    array arraytwo [%EVAL(&arg+1)] _temporary_;
    sum=0;
    %do i = 1 %to %EVAL(&arg+1);
        sum=sum+&i;
        arraytwo[&i]=sum;
        %end;
    return=arraytwo[&arg+1];
    %mend test;

/* This is ok */
data dat1;
    %test(arg=9);
run;

data dat2;
    input M;
    cards;
5
6
7
;
run;

/* This give an error= A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: M+1 */
data dat3;
    set dat2;
    %test(arg=M);
run;

那么问题是为什么它在上次测试中会出现错误?谢谢。

This is related to this question: SAS macro variable change.

The code below explains the problem:

%macro test (arg=); 
    options  mlogic mprint symbolgen;
    array arraytwo [%EVAL(&arg+1)] _temporary_;
    sum=0;
    %do i = 1 %to %EVAL(&arg+1);
        sum=sum+&i;
        arraytwo[&i]=sum;
        %end;
    return=arraytwo[&arg+1];
    %mend test;

/* This is ok */
data dat1;
    %test(arg=9);
run;

data dat2;
    input M;
    cards;
5
6
7
;
run;

/* This give an error= A character operand was found in the %EVAL function or %IF condition where a numeric
operand is required. The condition was: M+1 */
data dat3;
    set dat2;
    %test(arg=M);
run;

So the question is why does it bug in the last test? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

本王不退位尔等都是臣 2024-11-04 04:27:41

如果您碰巧使用 SAS 9.2 或更高版本,您可能需要查看 proc fcmp 来创建一个函数来执行此操作。

如果将其编写为函数而不是宏,则可以传入将解析为数值的数据集变量 - 或直接传递数值。例如,尝试以下代码:

proc fcmp outlib=work.funcs.simple;
  function sumloop(iter);
    x=1;
    do i=1 to iter+1;
      x+i;
    end;
    return(x);
  endsub;
run;

/* point to the location the function was saved in */
option cmplib=work.funcs; 

data _null_;
  input M;
  y=sumloop(M); /* data set variable */
  z=sumloop(9); /* static numeric value */
  put M= @7 y= @14 z= @20 ;
cards;
1
2
3
4
5
6
7
8
9
;
run;

/* My log looks like this:

14   data _null_;
15       input M;
16       y=sumloop(M); /* data set variable */
17       z=sumloop(9); /* static numeric value */
18       put M= @7 y= @14 z= @20 ;
19       cards;

M=1   y=3    z=55
M=2   y=6    z=55
M=3   y=10   z=55
M=4   y=15   z=55
M=5   y=21   z=55
M=6   y=28   z=55
M=7   y=36   z=55
M=8   y=45   z=55
M=9   y=55   z=55
*/

If you happen to be using SAS 9.2 or later you might want to look at proc fcmp to create a function to do this.

If you write it as a function instead of a macro, you can pass in data set variables that would resolve to numeric values - or pass numeric values directly. For example, try this code:

proc fcmp outlib=work.funcs.simple;
  function sumloop(iter);
    x=1;
    do i=1 to iter+1;
      x+i;
    end;
    return(x);
  endsub;
run;

/* point to the location the function was saved in */
option cmplib=work.funcs; 

data _null_;
  input M;
  y=sumloop(M); /* data set variable */
  z=sumloop(9); /* static numeric value */
  put M= @7 y= @14 z= @20 ;
cards;
1
2
3
4
5
6
7
8
9
;
run;

/* My log looks like this:

14   data _null_;
15       input M;
16       y=sumloop(M); /* data set variable */
17       z=sumloop(9); /* static numeric value */
18       put M= @7 y= @14 z= @20 ;
19       cards;

M=1   y=3    z=55
M=2   y=6    z=55
M=3   y=10   z=55
M=4   y=15   z=55
M=5   y=21   z=55
M=6   y=28   z=55
M=7   y=36   z=55
M=8   y=45   z=55
M=9   y=55   z=55
*/
软的没边 2024-11-04 04:27:41

我不得不说我不完全确定你想做什么;但这能给你你想要的结果吗?上面代码的问题在于您尝试组合数据集变量和宏变量的方式——它并不像人们希望的那么容易做到......

%macro test (argList=, totNumObs=);
    %local arg;
    %local j;
    %local i;
    %do j = 1 %to &totNumObs;
        %let arg = %scan(&argList, &j); 
        array array&j [%EVAL(&arg+1)] _temporary_;
        sum = 0;
        %do i = 1 %to %EVAL(&arg+1);
            sum = sum+&i;
            array&j[&i] = sum;
        %end;
        return = array&j[&arg+1];
        output;
    %end;
%mend test;

data dat2;
    input M;
    cards;
5
6
7
;
run;

proc sql noprint;
    select 
        count (*) into :numObs 
    from dat2 ;
    select 
        M into :listofMs separated by ' '
    from dat2
    order by M;
quit;

options  mlogic mprint symbolgen;

data dat3;
    %test(argList= &listofMs, totNumObs= &numObs);
run;

proc print data= dat3;
run;

I have to say I'm not entirely sure what you're trying to do; but does this give you the results you're looking for? The problem with your code above is the way you are trying to combine dataset variables and macro variables-- it isn't as easy to do as one might hope...

%macro test (argList=, totNumObs=);
    %local arg;
    %local j;
    %local i;
    %do j = 1 %to &totNumObs;
        %let arg = %scan(&argList, &j); 
        array array&j [%EVAL(&arg+1)] _temporary_;
        sum = 0;
        %do i = 1 %to %EVAL(&arg+1);
            sum = sum+&i;
            array&j[&i] = sum;
        %end;
        return = array&j[&arg+1];
        output;
    %end;
%mend test;

data dat2;
    input M;
    cards;
5
6
7
;
run;

proc sql noprint;
    select 
        count (*) into :numObs 
    from dat2 ;
    select 
        M into :listofMs separated by ' '
    from dat2
    order by M;
quit;

options  mlogic mprint symbolgen;

data dat3;
    %test(argList= &listofMs, totNumObs= &numObs);
run;

proc print data= dat3;
run;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文