SAS:在函数/子例程中查找数据/返回数组

时间:2018-04-18 12:02:19

标签: sas sas-macro

假设我喜欢执行以下操作(使用示例变量名称以获得更好的可读性):

  1. 获取参数InParameter并将其与数据集MyVar1中的变量MyData相匹配

  2. 返回已过滤观察的变量MyVar2的所有值

  3. 来自子程序/功能

  4. 我可以在proc sql / datastep里面使用

  5. 这是我到目前为止所得到的(显然不起作用):

    proc fcmp outlib=work.funcs.MyFunction;
        function MyFunction(InParameter $);
            array MyArray ... ; /* Here: Create an array with something like SELECT MyVar2 FROM MyData WHERE MyVar1 = Inparameter  */
            return(MyArray{});
        endsub;
        ;
    quit;
    
    options cmplib=work.funcs;
    
    data MyOutput;
        set Somedata;
        if MyVar2 in MyFunction("H20") then output;
    run;
    

    简而言之:

    • 可以从函数/子程序中访问数据集中的数据吗?
    • 函数/子程序可以返回数组吗?

    感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

不确定某个函数是否可以与IN运算符一起使用。您可能需要使用宏包装函数调用以生成正确的语法。在这种情况下,为什么不只是开始一个宏?

这是用于从数据集中的变量中提取值的通用宏。

%macro varlist
/*----------------------------------------------------------------------
Generate list of values from dataset
----------------------------------------------------------------------*/
(dataset     /* Input dataset */
,variable    /* Variable Name */
,quote=1     /* Add quotes around values? 1=Single 2=Double */
,comma=1     /* Add comma between values? */
,paren=1     /* Add parentheses around results? */
);
%local did sep &variable ;
%if &paren=1 %then (;
%let did=%sysfunc(open(&dataset));
%syscall set(did);
%do %while(0=%sysfunc(fetch(&did)));
  %let &variable=%qsysfunc(trim(%superq(&variable)));
  %if &quote=1 %then &sep.%sysfunc(quote(&&&variable,%str(%')));
  %else %if &quote=2 %then &sep.%sysfunc(quote(&&&variable));
  %else &sep.&&&variable;
  %if &comma=1 %then %let sep=,;
%end;
%let did=%sysfunc(close(&did));
%if &paren=1 %then );
%mend varlist;

示例电话:

%put %varlist(sashelp.class,name);
%put %varlist(sashelp.class(where=(sex='M')),age,quote=0,comma=0);

所以在你的情况下你可以像这样使用它:

data MyOutput;
  set Somedata;
  where MyVar2 in %varlist(Mydata(where=(MyVar1="H20")),MyVar2) ;
run;

答案 1 :(得分:1)

我们创建了一个名为%ds2list()的实用程序宏,它将执行您想要的过程。它不使用数组语句,但它实现了相同的结果。

宏只是以列表格式返回数据集中的值。以下是调用它的示例:

%put %ds2list(iDs=sashelp.class, iField=name, iQuote=1);

这将返回:

'Alfred','Alice','Barbara','Carol','Henry','James','Jane','Janet','Jeffrey','John','Joyce','Judy','Louise','Mary','Philip','Robert','Ronald','Thomas','William'

%ds2list()的默认行为是逗号分隔返回的值,但它非常灵活。您可以将分隔符更改为您选择的值(或无分隔符),您可以打开或关闭引号,或将它们从单引号更改为双引号,并且您可以提供通常在{{{ 1}}语句,例如set语句。

此外,因为宏是纯宏代码,所以您可以在SAS中的任何位置使用它。在你喜欢的任何proc / data / macro中。当我们想要返回一大堆ID时,我们会广泛使用它来调用ODBC直通。

以下是如何使用它的示例。首先创建一个表,其中包含要与列表值进行比较的值:

where=()

迭代我们要根据列表检查的值:

data keep;
  input name $;
  datalines;
Alfred
Carol
Janet
run;

返回:

data want;
  set keep;
  if name in (%ds2list(iDs=sashelp.class, iField=name, iQuote=1, iDsOptions=where=(sex='F'))) then do;
    output;
  end;
run;

您可以看到Alfred被排除在结果之外,因为他被Obs name === ===== 1 Carol 2 Janet 子句过滤掉了。

这是宏,我建议将它放在你的宏自动调用库中:

where=()

答案 2 :(得分:0)

你最好使用宏。

%macro subset(inParameter, indata, outdata);

proc sql noprint;
create table &outdata as
select * from &indata
   where myVar2 in (select distinct myVar2 from myData where myVar1 = "&inParameter);
quit;
%mend;

%subst(H20,Somedata,MyOutput);