SAS - 通过调用一个宏来构建一个新表,该宏具有作为参数传递的另一个表的变量

时间:2017-11-15 17:07:01

标签: sas

我已编写此代码来执行此操作:

  1. 读取表格中的记录" not_identified"一个接一个
  2. 对于一条记录传递" name_firstname"变量为名为" mCalcul_lev_D33",
  3. 的宏
  4. 然后,宏计算作为参数传递的变量与变量" name_firstname_in_D33"的所有值之间的Levenstein。 in" data_all"表,
  5. 如果Levenstein返回的值小于或等于" 3",则记录" data_all"被复制到" lev_D33"表
  6. rsubmit;
    %macro mCalcul_lev_D33(theName);
      data result.lev_D33;
       set result.data_all;
       name_LEV=complev(&theName, name_firstname_in_D33);
       if name_LEV<=3 then output;
      run;
    %mend mCalcul_lev_D33;
    endrsubmit;
    
    rsubmit;
    data _null_;
      set result.not_identified;
      call execute ('%mCalcul_lev_D33('||name_firstname||')');
    ;
    run;
    endrsubmit;
    

    &#34; data_all&#34;中有53700000条记录。代码自昨天开始运行。因为我看不到结果,所以我在问:

    1. 代码是否符合我的要求?
    2. 如果我想编写怎么编码&#34; name_firstname&#34; (变量像参数一样传递)在&#34; lev_D33&#34;?
    3. 的每个记录的开头

      谢谢!

2 个答案:

答案 0 :(得分:1)

D.O:

我认为你的宏正在使任务变得更加困难。似乎存在编码问题,因为not_identified记录中的每一行都将导致重建result.lev_D33。如果长时间运行的程序完成,则lev_D33输出数据集将仅对应于最后一个not_identified。

您正在进行完全外部联接,比较流程中的ALL_COUNT * NOT_IDENT_COUNT行。

  • not_identified中有多少行?希望远远少于data_all。
  • result libname是指向网络驱动器还是远程服务器?
    网络i / o可以使事情运行很长时间,甚至可以赢得网络团队的电话。

DATA Step中的完全外连接可以使用嵌套循环和内循环SET上的point =来完成。在DATA Step中,外部循环是隐式循环。

请考虑以下示例代码:

data all_data;
  do row = 1 to 100;
    length name_firstname $20;  
    name_firstname 
      =  repeat (byte(65 + mod(row,26)), 4*ranuni(123))
      || repeat(byte(65 + 26*ranuni(123)), 4*ranuni(123))
    ;
    output;
  end;
run;

data not_identified;
  do row = 1 to 10;
    length name_firstname $20;
    name_firstname = repeat (byte(65 + mod(row,26)), 10*ranuni(123));
    output;
  end;
run;


data lev33;
  set all_data;
  do check_row = 1 to check_count;
    set not_identified (keep=name_firstname rename=name_firstname=check_name)
        nobs=check_count 
        point=check_row
    ;
    name_lev = complev (check_name, name_firstname);
    if name_lev <= 3 then output;
  end;
run;

此方法在移动到下一行之前测试每个not_identified。当all_data非常大并且您可能希望一次处理它的块时,这是一种有用的方法。块处理是开始宏编码的合适位置:

%macro do_chunk (FROM_OBS=, TO_OBS=);
  data lev33_&FROM_OBS._&TO_OBS;
    set all_data (firstobs=&FROM_OBS obs=&TO_OBS);
    do check_row = 1 to check_count;
      set not_identified (keep=name_firstname rename=name_firstname=check_name)
          nobs=check_count 
          point=check_row
      ;
      name_lev = complev (check_name, name_firstname);
      if name_lev <= 3 then output;
    end;
  run;
%mend;

%macro do_chunks;
  %local index;
  %do index = 1 %to 100 %by 10;
    %do_chunk ( FROM_OBS=&index, TO_OBS=%eval(&index+9) )
  %end;
%mend;

%do_chunks

您可以绕过do_chunks并手动调用do_chunk以适应您选择的各种范围,从而完成整个过程。

答案 1 :(得分:0)

感谢@Richard。我用你的第二个例子来编写这段代码:

rsubmit;
  data result.lev_D33;
    set result.not_identified (firstobs=1 obs=10);
    do check_row = 1 to 1000000;
      set &lib..data_all (firstobs=1 obs=1000000) point=check_row;
      name_lev = complev (name_firstname, name_firstname_D3);
      if name_lev <= 3 then output;
    end;
  run;
endrsubmit ;

它就像我想要的那样工作。

在此示例中,我将not_identified表中的name_firstname与data_all中的所有name_firstname_D3进行比较。如果COMPLEV小于或等于3,则2条记录的合并在结果表“lev_D33”中(来自not_identified的一条记录合并为data_all中的一条记录)。

为了进行测试,我从not_identified中删除了10条记录,并试图在1000000 data_all中找到名称和firstnames的一致性。