SAS-如何从SAS宏返回值?
我想从我创建的SAS宏返回一个值,但我不确定如何返回。宏计算数据集中的观察数。我希望返回观察值的数量SAS-如何从SAS宏返回值?,sas,Sas,我想从我创建的SAS宏返回一个值,但我不确定如何返回。宏计算数据集中的观察数。我希望返回观察值的数量 %macro nobs(library_name, table_name); proc sql noprint; select nlobs into :nobs from dictionary.tables where libname = UPCASE(&library_name) and memname = UPCASE(&table_n
%macro nobs(library_name, table_name);
proc sql noprint;
select nlobs into :nobs
from dictionary.tables
where libname = UPCASE(&library_name)
and memname = UPCASE(&table_name);
quit;
*return nobs macro variable;
&nobs
%mend;
%let num_of_observations = %nobs('work', 'patients');
此外,我希望宏中使用的
&nobs
宏变量是该宏的局部变量,而不是全局变量。如何才能做到这一点?除非仅使用宏语句编写,否则无法从函数样式宏“返回”值。昆汀的链接提供了一个如何做到这一点的例子
例如,您不能使用这样的宏,因为PROC SQL不能在<代码> %PUT/<代码>语句的中间执行(这可能是其他更复杂的处理方法,例如:代码> DOUBUL,但不是您编写的方法)。 在没有重大更改的情况下,最好创建一个全局宏变量,并在后续语句中使用它
若要创建原始宏的本地宏变量,必须首先通过宏定义中的
%local
语句声明它。SAS宏插入代码。它永远不会返回值,尽管在某些情况下可以模拟函数,通常需要类似的解决方法
%nobs(work, patients, toReturn=num_of_observations )
**为了帮助您理解发生了什么,我建议打印宏在日志中插入的代码:
options mprint;
我们将要填充的宏变量的名称传递给宏,我发现最实用的方法是
- 不要求我的宏的用户在库名和成员名周围加引号
- 使变量名成为命名的宏变量,这样我们就可以给它一个默认值 %宏nobs(库名称、表名称、toReturn=nobs)
- 如果它存在,则在该宏外部已知李>
- 否则,如果我们在这里创建它,默认情况下它将是本地的,当我们离开宏时它将丢失
%if not %symexist(&toReturn.) %then %global &toReturn.;
- 使用SASHELP.VTABLE,SAS提供的元数据视图
- 添加我在宏调用中省略的引号(“,而不是“”:宏变量不在单个qoutes中替换)
- 使用宏%upcase函数代替SAS upcase函数,因为它有时会提高性能
%修补proc sql noprint; select nobs into :&toReturn. from sashelp.vtable where libname = %UPCASE("&library_name.") and memname = %UPCASE("&table_name."); quit;
%macro test_nobs();
%nobs(sashelp, class); ** will return the results in nobs **;
%nobs(sashelp, shoes, toReturn=num_of_shoes);
%let num_of_cars = ;
%nobs(sashelp, cars, toReturn=num_of_cars);
%put NOTE: inside test_nobs, the following macro variables are known;
%put _user_;
%mend;
%test_nobs;
%put NOTE: outside test_nobs, the following macro variables are known;
%put _user_;
编写宏这样的函数有什么问题? i、 e.可以用作
%let myVar=%myMacro(myArgument)
- 您可以使用用户编写的宏,就像它是一个函数一样,如果您所做的只是
- 调用一些类似宏函数的
%doSomething(with someting)
- 使用
语句为宏变量赋值%let someVar=
- “返回”您的结果,通常在
%mend
- 调用一些类似宏函数的
- 一旦在宏中包含
或proc
步骤,这将不再有效data
- 幸运的是,%sysFunc()起到了解救作用,因此我们可以使用任何数据步函数
- 这包括低级功能,如
、open
和fetch
,它们甚至可以访问您的数据close
- 书呆子们可以用它做很多事情,但即使你是书呆子,你的老板也很少给你时间这么做
允许将一些数据步骤语句打包到子例程或函数中proc fcmp
- 此函数用于数据步骤,可在
%sysfunc()
- 在此函数中,您可以调用
立即在后台执行任何宏run\u macro
- 没有参数
- 使用一些全局宏变量
- 在全局宏变量中“返回”其结果
** macro nobsHelper retrieves the number of observations in a dataset
Uses global macro variables:
nobsHelper_lib: the library in which the dataset resides, enclosed in quotes
nobsHelper_mem: the name of the dataset, enclosed in quotes
Writes global macro variable:
nobsHelper_obs: the number of observations in the dataset
Take care nobsHelper exists before calling this macro, or it will be ost
**;
%macro nobsHelper();
** Make sure nobsHelper_obs is a global macro variable**;
%global nobsHelper_obs;
proc sql noprint;
select nobs
into :nobsHelper_obs
from sashelp.vtable
where libname = %UPCASE(&nobsHelper_lib)
and memname = %UPCASE(&nobsHelper_mem);
quit;
%* uncomment these put statements to debug **;
%*put NOTE: inside nobsHelper, the following macro variables are known;
%*put _user_;
%mend;
步骤2:编写助手函数
**Functions need to be stored in a compilation library;
options cmplib=sasuser.funcs;
** function nobsHelper, retrieves the number of observations in a dataset
Writes global macro variables:
nobsHelper_lib: the library in which the dataset resides, enclosed in quotes
nobsHelper_mem: the name of the dataset, enclosed in quotes
Calls the macro nobsHelper
Uses macro variable:
nobsHelper_obs: the number of observations in the dataset
**;
proc fcmp outlib=sasuser.funcs.trial;
** Define the function and specity it should be called with two character vriables **;
function nobsHelper(nobsHelper_lib $, nobsHelper_mem $);
** Call the macro and pass the variables as global macro variables
** The macro variables will be magically qouted **;
rc = run_macro('nobsHelper', nobsHelper_lib, nobsHelper_mem);
if rc then put 'ERROR: calling nobsHelper gave ' rc=;
** Retreive the result and pass it on **;
return (symget('nobsHelper_obs'));
endsub;
quit;
** macro nobs retrieves the number of observations in a dataset
Parameters:
library_name: the library in which the dataset resides
member_name: the name of the dataset
Inserts in your code:
the number of observations in the dataset
Use as a function
**;
%macro nobs(library_name, member_name);
%sysfunc(nobsHelper(&library_name, &member_name));
%* Uncomment this to debug **;
%*put _user_;
%mend;
%let num_carrs = %nobs(sasHelp, cars);
%put There are &num_carrs cars in sasHelp.Cars;
Data aboutClass;
libname = 'SASHELP';
memname = 'CLASS';
numerOfStudents = %nobs(sasHelp, class);
run;
步骤3:编写一个方便的宏来使用帮助程序
**Functions need to be stored in a compilation library;
options cmplib=sasuser.funcs;
** function nobsHelper, retrieves the number of observations in a dataset
Writes global macro variables:
nobsHelper_lib: the library in which the dataset resides, enclosed in quotes
nobsHelper_mem: the name of the dataset, enclosed in quotes
Calls the macro nobsHelper
Uses macro variable:
nobsHelper_obs: the number of observations in the dataset
**;
proc fcmp outlib=sasuser.funcs.trial;
** Define the function and specity it should be called with two character vriables **;
function nobsHelper(nobsHelper_lib $, nobsHelper_mem $);
** Call the macro and pass the variables as global macro variables
** The macro variables will be magically qouted **;
rc = run_macro('nobsHelper', nobsHelper_lib, nobsHelper_mem);
if rc then put 'ERROR: calling nobsHelper gave ' rc=;
** Retreive the result and pass it on **;
return (symget('nobsHelper_obs'));
endsub;
quit;
** macro nobs retrieves the number of observations in a dataset
Parameters:
library_name: the library in which the dataset resides
member_name: the name of the dataset
Inserts in your code:
the number of observations in the dataset
Use as a function
**;
%macro nobs(library_name, member_name);
%sysfunc(nobsHelper(&library_name, &member_name));
%* Uncomment this to debug **;
%*put _user_;
%mend;
%let num_carrs = %nobs(sasHelp, cars);
%put There are &num_carrs cars in sasHelp.Cars;
Data aboutClass;
libname = 'SASHELP';
memname = 'CLASS';
numerOfStudents = %nobs(sasHelp, class);
run;
最后使用它
**Functions need to be stored in a compilation library;
options cmplib=sasuser.funcs;
** function nobsHelper, retrieves the number of observations in a dataset
Writes global macro variables:
nobsHelper_lib: the library in which the dataset resides, enclosed in quotes
nobsHelper_mem: the name of the dataset, enclosed in quotes
Calls the macro nobsHelper
Uses macro variable:
nobsHelper_obs: the number of observations in the dataset
**;
proc fcmp outlib=sasuser.funcs.trial;
** Define the function and specity it should be called with two character vriables **;
function nobsHelper(nobsHelper_lib $, nobsHelper_mem $);
** Call the macro and pass the variables as global macro variables
** The macro variables will be magically qouted **;
rc = run_macro('nobsHelper', nobsHelper_lib, nobsHelper_mem);
if rc then put 'ERROR: calling nobsHelper gave ' rc=;
** Retreive the result and pass it on **;
return (symget('nobsHelper_obs'));
endsub;
quit;
** macro nobs retrieves the number of observations in a dataset
Parameters:
library_name: the library in which the dataset resides
member_name: the name of the dataset
Inserts in your code:
the number of observations in the dataset
Use as a function
**;
%macro nobs(library_name, member_name);
%sysfunc(nobsHelper(&library_name, &member_name));
%* Uncomment this to debug **;
%*put _user_;
%mend;
%let num_carrs = %nobs(sasHelp, cars);
%put There are &num_carrs cars in sasHelp.Cars;
Data aboutClass;
libname = 'SASHELP';
memname = 'CLASS';
numerOfStudents = %nobs(sasHelp, class);
run;
我知道这很复杂但至少所有无聊的工作都完成了。
你可以在老板接受的时间内复制、粘贴和修改这些内容。
; 我将回答斑比在评论中提出的核心问题: 这里我主要关心的是如何从宏返回值 我要用一种重要的方式和德克争论。他说: SAS宏插入代码。它永远不会返回值,尽管在某些情况下可以模拟函数 我不同意。SAS宏返回插入到处理流中的文本。回报绝对是一个合适的术语。当文本恰好是单个数字时,可以说它返回一个值 但是,如果宏除返回一个值外还包含宏语句,则该宏只能返回该值。也就是说,每一行都必须以
%
开头。任何不以%
开头的内容都将被返回(一些以%
开头的内容也可能被返回)
因此,重要的问题是,如何仅返回宏中的值
在某些情况下,如本例,完全可以只使用宏代码。事实上,在许多情况下,这在技术上是可能的——尽管在许多情况下,这比你应该做的工作要多 Jack Hamilton的链接中包含了一个适用于此的示例。他驳斥了这个例子
%global sum;
%macro get_something_back(input1, input2, outvar);
%let &outvar = &sysevalf(&input1 + &input2);
%mend;
%get_something(1, 2, sum);