我有一个包含一行和四列的表。我想创建在每列之后命名的4个宏变量,其中值设置为1行中的值。
如果是R,我可以直接使用以下内容访问这些值:
newvar1=tablename[1,1]
newvar2=tablename[1,2]...
我是否还要从表中选择值并设置等于该值的宏变量?
类似于:
%macrovar1=tablename[1,1]...
除了显然,等号的右侧是R代码而不是SAS。
由于
答案 0 :(得分:4)
你可以使用proc sql这样做:
proc sql noprint inobs=1;
select name into :my_val from sashelp.class;
quit;
%put &my_val;
或者您可以使用datastep中的call symput
,如下所示:
data _null_;
set sashelp.class(obs=1);
call symput('my_val',name);
run;
对于更灵活的东西,我们使用一个实用程序宏,它允许我们从代码中的任何位置检查值。我稍微修改了它以满足您的要求,但用法如下:
%let my_val = %get_val(iDs=sashelp.class, iField=name);
您也可以在proc或datastep中间使用它,如下所示:
data _null_;
my_value = "%get_val(iDs=sashelp.class, iField=name)";
run;
甚至:
proc sql noprint;
create table want as
select * from sashelp.class
where name = "%get_val(iDs=sashelp.class, iField=name)"
;
quit;
这是宏定义:
%macro get_val(iDs=, iField=);
%local dsid pos rc result cnt value;
%let result=;
%let cnt=0;
/*
** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
*/
%if "&iDs" ne "" and "&iField" ne "" %then %do;
%let dsid=%sysfunc(open(&iDs,i));
%if &dsid %then %do;
%let pos=%sysfunc(varnum(&dsid,&iField));
%if &pos %then %do;
%let rc=%sysfunc(fetch(&dsid));
%if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
%let value = %qsysfunc(getvarc(&dsid,&pos));
%if "%trim(&value)" ne "" %then %do;
%let value = %qtrim(&value);
%end;
%end;
%else %do;
%let value = %sysfunc(getvarn(&dsid,&pos));
%end;
&value
%end;
%else %do;
%put ERROR: MACRO.GET_VAL.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
%end;
%end;
%else %do;
%put ERROR: MACRO.GET_VAL.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put ERROR: MACRO.GET_VAL.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
%end;
%mend;
上面的宏是找到{%{3}}的%ds2list宏的缩写版本。
答案 1 :(得分:3)
有几种方法,但最简单的是:
data _null_;
set have;
if _n_=1 then do;
call symputx('macrovar1',var1);
*more of these;
end;
stop;
run;
打开数据集,然后如果在第一行(_n_
是数据步骤循环的迭代,在大多数情况下是第一行),使用call symputx将其值赋给宏变量
我会注意到你应该记住,SAS宏变量不是数据变量,没有数据类型(总是文本),通常不会像你那样用来存储数据在R.使用向量