使用 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*/
两个问题:
- 我在 %macro2 中遗漏了什么?
- 您是否看到我没有使用的更好的解决方案?这些文件的结构不同,不可堆叠,请注意。
这里有个小错别字,您需要在 LAST 前面使用 & 而不是 %。
%do i=&first. %to %last. %by 1;
应该是:
%do i=&first. %to &last. %by 1;
除非您使用名为 last 的单独宏来确定循环结束。但在那种情况下,您可能不会还有一个名为 last 的参数。
如果您正在寻找替代选项,我通常建议使用数据步或 CALL EXECUTE 而不是宏循环来一次读取所有内容,因为在我看来它们更容易调试。
从您的日志中我们可以看到一个句点被插入到输出数据集名称中。只需在您的宏定义中删除多余的句点即可。
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)
我有一个 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*/
两个问题:
- 我在 %macro2 中遗漏了什么?
- 您是否看到我没有使用的更好的解决方案?这些文件的结构不同,不可堆叠,请注意。
这里有个小错别字,您需要在 LAST 前面使用 & 而不是 %。
%do i=&first. %to %last. %by 1;
应该是:
%do i=&first. %to &last. %by 1;
除非您使用名为 last 的单独宏来确定循环结束。但在那种情况下,您可能不会还有一个名为 last 的参数。
如果您正在寻找替代选项,我通常建议使用数据步或 CALL EXECUTE 而不是宏循环来一次读取所有内容,因为在我看来它们更容易调试。
从您的日志中我们可以看到一个句点被插入到输出数据集名称中。只需在您的宏定义中删除多余的句点即可。
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)