【问题标题】:SAS macro variable in datalines inside a macro宏内数据行中的 SAS 宏变量
【发布时间】:2017-09-02 01:46:04
【问题描述】:

我的问题如下 - 我有这段代码可以正常工作,并将保存到宏变量中的字符添加到表中:

%let year=2015;
data example;
input year $40.;
years=dequote(resolve(quote(year)));
datalines;
&year
;
run;

输出:

现在我想在宏内部做同样的事情,代码如下:

  %macro pokus();
  %let year=2015;
  data example;
  input year $40.;
  years=dequote(resolve(quote(year)));
  datalines;
  &year
  ;
  run;
  %mend pokus;
  %pokus;

但我收到一条错误消息:

为什么会这样?有没有一些简单的方法可以将宏变量添加到宏内的表中? 我需要它来执行这种类型的循环:

 %macro pokus();
 %do i=2015 %to 2017;
 %let year=&i.;
 data example;
 input year $40.;
 years=dequote(resolve(quote(year)));
 datalines;
 &year
 ;
 run;

 ....additional code .....
 %end;
 %mend pokus;
 %pokus;

补充说明—— 这是以这种方式继续进行的更复杂练习的一部分:

data z;
length roky mesic mesic2 saz $100;
input roky mesic mesic2 saz; 
datalines;
2012 01 1 k
2012 02 2 h
2012 03 3 j
2012 04 4 x
2012 05 5 l
2012 06 6 m
;
run;

proc sql;
select count (*) into: pocet from z;
quit;

%macro rok();
%do i=1 %to &pocet;
data _null_;
set z (obs= &i);
call symputx("roky",roky);
call symputx("mesic",mesic);
call symputx("mesic2",mesic);
call symputx("saz",saz);
run;
...... additional code .....
%end;
%mend rok;
%rok;

现在我想让它动态化,即首先计算列“roky”的所有内容,其值为 2012,而不是 2013、2014 等。但我无法在此构造之上构建另一个宏,以更改 z 表中的“roky”列。

感谢您的帮助。

【问题讨论】:

  • 你到底为什么要取消引用->解析->引用宏变量?
  • 我已经用谷歌搜索过 (support.sas.com/kb/43/295.html) - 对我来说,这是将存储在宏变量中的值放入由数据线定义的表示例中的唯一方法
  • 你所做的仍然没有任何意义;看来您应该改为发布您最终真正想做的事情,而不仅仅是您的方法,因为在我看来,这不是一种合乎逻辑的方法。发布一个新问题,并包含您的程序的全部目的(或者至少,不仅仅是“附加代码”——这通常是做什么的?)。
  • 我终于找到了更简单的解决方案。非常感谢。

标签: sas


【解决方案1】:

你要么没有解释一些重要的细节,要么你以一种完全没有必要的极其复杂的方式来做这件事。

您的问题的直接答案在错误消息中:CARDS or DATALINES statements cannot be used in macros.

但解决方案是您不应该以这种方式使用数据线。这不是将宏变量放入数据集的正确方法。

%let year=2015;
data example;
  years=&year.;
run;

容易多了,不是吗?这在宏中是否可以正常工作。

如果您是通过提示或其他方式获取此宏变量,您可能需要%unquote(&year),但您仍然可以在原地执行此操作。

data example;
  years = %unquote(&year.);
run;

【讨论】:

  • 感谢您的建议。我添加了对我面临的问题的更详细描述。
【解决方案2】:

您还没有解释为什么需要使用内联数据。这是宏内部无法做到的。

如果只是这样,您可以将字符串 '&year' 放入字符变量中,那么为什么不直接使用赋值语句呢?确保使用单引号,以便宏处理器在编译数据步骤之前不会解析 &year。

那么你的第一个数据步骤可能看起来像这样。

%let year=2015;
data example;
  year='&year';
  years=dequote(resolve(quote(year)));
run;

当然,如果您只想检索单个宏变量的值,那么使用 SYMGET() 函数会更容易。

%let year=2015;
data example;
  years=symget('year');
run;

您的问题的其余部分看起来您可能想从元数据表中的数据中驱动一个宏? SO上已经有类似的问题了。一种解决方案是定义宏以使用参数并使用 CALL EXECUTE() 为元数据表中的每一行生成一个宏调用。所以是这样的:

data _null_;
  set z ;
  call execute(cats('%nrstr(%rok)('
    ,'roky=',roky
    ,'mesic=',mesic
    ,'mesic2=',mesic2
    ,'saz=',saz
    ,')'
  ));
run;

会产生如下调用:

%rok(roky=2012,mesic=01,mesic2=1,saz=k)
%rok(roky=2012,mesic=02,mesic2=2,saz=h)
...

【讨论】:

  • 我正在使用内联数据,因为这是我用来定义元数据表并从其数据运行宏的方式。或者有没有其他简单的方法(即使对于元数据表的某些列包含字符串的情况),如何做到这一点?
  • 不确定我是否理解您评论中的问题。如果你想进入宏,你当然可以将字符串值作为带引号的字符串传递。只需生成带引号的调用,quote() 函数会有所帮助,并设计宏以期望参数值包含引号。
猜你喜欢
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-02
  • 2021-12-07
相关资源
最近更新 更多