在 SAS 中调用 n 个宏的宏

问题描述 投票:0回答:1

我编写了一段代码,将创建多个包含 ID 的宏变量。然而,宏变量只能包含 65534 个字符。我的每个宏变量 ACC_i 都包含 65k 个变量。我想创建包含宏变量 ACC_1 - ACC_i 的宏变量,因此在代码中使用时将调用所有宏。

这是我到目前为止的代码,请提供帮助

%MACRO LOOP();
proc sql; select Count(*) as CNT ,MAX(LENGTH(Column1)) FORMAT 2.0 as LEN into: CNT, :LEN from table
; quit;
%put &CNT. &LEN.;

%let RUNS = %sysfunc(CEIL(&CNT./(65534/&LEN.)));
%LET OBS = %sysfunc(FLOOR(((65534/&LEN.))));

data TEST;
set &table.;
run;

%put &RUNS.;
%put &OBS.;
%let ACC = .;
%global i;
%DO i = 1 %to &RUNS.;
    %global ACC_&i.;
    proc sql inobs=&OBS.; 
        select input(&ID.,16.) FORMAT 16. as ACC_&i. into: ACC_&i. SEPARATED BY " ," 
        from TEST 
    ;quit;

    data TEST;
    set TEST nobs=count;
    if _n_ <= &OBS. then delete;
    run;

    
%END;
%mend;
%LOOP();

sas macros
1个回答
0
投票

根据您想要做什么,可能有一种通过使用表格来实现此目的的更佳方法。但是,这是一个有趣的编程挑战,所以这里有一个可以满足您需求的解决方案。

最简单的方法是创建一个表,将您的 ID 分成几组。我们将累计计算所有值的长度,加上 2 以考虑空格和逗号,并在超过 65534 时增加组计数器。

请注意,如果您的 ID 是数字,请先使用

strip(put(num_var, 32.))
将其转换为字符,否则 SAS 将不会给出预期的答案。

/* Sample data */
data have;
    do i = 1 to 100000;
        id = put(rand('integer', 100000), z8.);
        output;
    end;
    drop i;
run;

data id_groups;
    set have;
    retain group;

    if(_N_ = 1) then group = 1;
 
    /* Add +2 to account for ', ' */
    cumulative_len+(length(id)+2);

    if(cumulative_len > 65534) then do;
        group+1;
        cumulative_len = length(id)+2;
    end;

    call symputx('ngroups', group);
    keep id group;
run;
id          group   cumulative_len
00058330    1       10
00099363    1       20
00058789    1       30
...         ...     ...
00051947    1       65520
00066223    1       65530
00064104    2       10
00060774    2       20
...

我们知道组的总数,因此我们将循环它们并为每个组创建一个宏变量。然后我们将所有这些保存到一个名为

all_macvars
的宏变量中。

%macro create_vars;
    %global all_macvars;

    %do i = 1 %to &ngroups;
        %global id_&i.;

        proc sql noprint;
            select id
            into :id_&i. separated by ', '
            from id_groups
            where group=&i
            ;
        quit;

        %let all_macvars = &all_macvars %nrstr(&id_)&i.;
    %end;
%mend;
%create_vars;

%put &all_macvars
%put &id_1
&id_1 &id_2 &id_3 &id_4 &id_5 &id_6 
&id_7 &id_8 &id_9 &id_10 &id_11 &id_12 
...

00058330, 00099363, 00058789, 00085747, 00082469, 
00028057, 00064740, 00038192, 00044896, 00087579, 
00051839, 00084268, 00027839, 00093355, 00018740,
...
© www.soinside.com 2019 - 2024. All rights reserved.