【发布时间】:2021-01-22 22:49:13
【问题描述】:
提前感谢您提出的任何建议。
我第一次在 SAS 工作以完成一项(理论上)简单的任务。我在 Windows 目录中有一个父文件夹,其中包含几个子文件夹。子文件夹没有系统地命名。例如,如果父文件夹名为“W:/Documents/ParentFolder/”,则子文件夹可能是“W:/Documents/ParentFolder/ABC1D26/”和“W:/Documents/ParentFolder/HG34A/”。
每个子文件夹包含多个 SAS 数据集。在任何特定的子文件夹中,一些 SAS 数据集具有 .sas7bdat 扩展名,而另一些具有 .sd2 扩展名。此外,没有两个子文件夹必须具有相同数量的数据集,并且数据集也没有系统地命名。
我想在 SAS 中编写一个程序,它查看每个子文件夹,加载它找到的任何 .sas7bdat 或 .sd2 数据集,并将数据集作为 .dta 文件导出到不同的文件夹中。
每个子文件夹中有太多 SAS 数据集,无法为每个数据集手动执行此任务,但没有太多子文件夹,我无法手动将子文件夹名称提供给 SAS。下面是我尝试完成此任务的程序的注释版本。不幸的是,我遇到了很多错误,这无疑是由于我对 SAS 缺乏经验。
例如,SAS 给出以下错误:“错误:无效的逻辑名称;” “错误:文件名语句中的错误;”和“错误:无效的 DO 循环控制信息;”等等。
谁能给点建议?
%macro sas_file_converter();
/* List the sub-folders containing SAS files in the parent folder */
%let folder1 = W:\Documents\ParentFolder\ABC1D26;
%let folder2 = W:\Documents\ParentFolder\HG34A;
/* Start loop over the sub-folders. In each sub-folder, identify all the files, extract the file names, import the files, and export the files. */
%do folder_iter = 1 %to 2;
/* Define the sub-folder that is the focus of this iteration of the loop */
filename workingFolder "&&folder&folder_iter..";
/* Extract a list of datasets in this sub-folder */
data datasetlist;
length Line 8 dataset_name $300;
List = dopen('workingFolder');
do Line = 1 to dnum(List);
dataset_name = tranwrd(tranwrd(lowcase(trim(dread(List,Line))),".sas7bdat",""),".sd2","");
output;
end;
drop List Line;
run;
/* Get number of datasets in this sub-folder */
proc sql nprint;
select count(*)
into :datasetCount
from WORK.datasetlist;
quit;
/* Loop over datasets in the sub-folder. In each iteration of the loop, load the dataset and export the dataset. */
%do dataset_iter = 1 %to &datasetCount.;
/* Get the name of the dataset which is the focus of this iteration */
data _NULL_;
set WORK.DATASETLIST (firstobs=&dataset_iter. obs=&dataset_iter.);
call symput("inMember",strip(dataset_name));
end;
/* Set the libname */
LIBNAME library '&folder&folder_iter..';
/* Load the dataset */
data new;
set library.&inMember.;
run;
/* Export the dataset */
proc export data=library.&inMember.
file = "W:\Documents\OutputFolder\&inMember..dta"
dbms = stata replace;
run;
%end;
%end;
%mend;
【问题讨论】:
-
您是否将 DTA 文件全部放入同一个输出文件夹中?如果在多个源文件夹中存在同一成员导致名称冲突怎么办?如果没有名称冲突,那么您只需要定义一个指向所有输入文件夹的 libref。
-
就个人而言,我会以不同的方式分解它。首先,您有一个步骤可以轻松找到所有文件夹/文件。您浏览此文件并确定是否有重复项,查找名称。然后它是一个简单的导出,我可能会通过 CALL EXECUTE 调用,而不是通过循环宏 - 当您单独测试每个组件时,更容易完全调试和测试。
-
这里的代码说明了这种方法。初始文件列表代码是从 SAS 文档 - 宏附录中窃取的。 github.com/statgeek/SAS-Tutorials/blob/master/…
-
只是想插话:我真的很喜欢你的代码——非常干净、易于阅读且格式正确。