使用 proc 导入读取 csv 文件的 SAS 宏循环

SAS macro loop to read csv files with proc import

我有一个 csv 文件目录,每个文件的名称都以字母 m 开头并以数字结尾。有十二个文件 - m6 到 m17。

我想读入它们并将它们作为单独的数据集处理。我已经写了两个试图这样做的宏。 Macro1 有效。 Macro2 中断。如果我能让它工作,我更喜欢 Macro2,以避免不必要的位,比如我创建 %rawfiles、调用 %sysfunc 等。

宏 1:

%let rawcsv = C:\ALL\dat\;

%let rawfiles = m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 m16 m17;

%macro1;

%do i = 1 %to %sysfunc(countw(&rawfile));
    %let rawfile = %scan(&rawfiles, &i);

proc import datafile="&&rawcsv.&&rawfile.csv" 
                 out=&rawfile replace
                dbms=csv; 
        guessingrows=500; 
run;
%end;
%mend;

%macro1;

宏 2:

%let rawcsv = C:\ALL\dat\;

%macro macro2(first=6, last=19);
%do i=&first. %to &last. %by 1;
proc import datafile="&&rawcsv..m&&i.csv" 
                 out=m&i replace 
                dbms=csv; 
        guessingrows=500;
run;
%end;
%mend;

%macro2;

%macro2 是我的拙劣模仿of this 解决方案。它 returns 出现以下错误:

MPRINT(MACRO2):   proc import datafile="C:\ALL\dat\m.6.csv" out=m.6 replace 
dbms=csv;
MPRINT(MACRO2):   ADLM;
MPRINT(MACRO2):   guessingrows=500;
MPRINT(MACRO2):   run;

ERROR: Library name is not assigned. /*repeats this error 14 times, once per file*/

两个问题:

  1. 我在 %macro2 中遗漏了什么?
  2. 您是否看到我没有使用的更好的解决方案?这些文件的结构不同,不可堆叠,请注意。

这里有个小错别字,您需要在 LAST 前面使用 & 而不是 %。

 %do i=&first. %to %last. %by 1;

应该是:

 %do i=&first. %to &last. %by 1;

除非您使用名为 last 的单独宏来确定循环结束。但在那种情况下,您可能不会还有一个名为 last 的参数。

如果您正在寻找替代选项,我通常建议使用数据步或 CALL EXECUTE 而不是宏循环来一次读取所有内容,因为在我看来它们更容易调试。

https://communities.sas.com/t5/SAS-Communities-Library/How-do-I-write-a-macro-to-import-multiple-text-files-that-have/ta-p/223627

从您的日志中我们可以看到一个句点被插入到输出数据集名称中。只需在您的宏定义中删除多余的句点即可。

MPRINT(MACRO2):   proc import datafile="C:\ALL\dat\m.6.csv" out=m.6 replace dbms=csv;

代码中额外的 & 可能会让您感到困惑。当宏处理器看到两个 & 时,它将它们转换为一个,然后重新处理字符串以进一步解析生成的宏变量引用。

当宏处理器可以判断名称已经结束时,宏变量名称后的句号就不需要了。但是有些地方需要句号。 代码中的一个地方是需要确保宏处理器知道名称结束的地方(宏变量被命名为 readcsv 而不是 readcsvm )。另一个是您要在宏变量值之后放置一个实际句点的位置。您需要在此处放置两个句点,因为宏处理器在计算宏变量值时会使用第一个句点。

在这个版本的 macro2 中,我在不需要的地方去掉了宏变量名后面的句点,只是为了强调需要句点的地方。

%let rawcsv = C:\ALL\dat\;

%macro macro2(first, last);
%local i ;
%do i=&first %to &last ;
proc import dbms=csv
  datafile="&rawcsv.m&i..csv" 
  out=m&i replace 
; 
  guessingrows=500;
run;
%end;
%mend macro2;

%macro2(first=6, last=19)