强制 proc export 为不存在的变量创建空白列
Forcing proc export to create blank column for non-existing variable
背景
我运行下面的宏在循环中导出了一些数据集。不幸的是,其中一些数据集有额外的变量。我的目的是以相同格式导出所有文件,其中 不存在的列作为空白提供 。
数据
这可以用以下数据集来说明。
dataA
varA varB
1 3
2 3
3 3
dataB
varA varB
9 4
9 4
9 4
dataC
varA varB varC
2 5 6
2 5 6
2 5 6
我希望我的 CSV 文件如下所示:
dataA.CSV
varA varB varC
1 3 .
2 3 .
3 3 .
dataB.CSV
varA varB varC
9 4 .
9 4 .
9 4 .
dataC.CSV
varA varB varC
2 5 6
2 5 6
2 5 6
宏
%macro export_data(dsnms);
* Get observations count;
PROC SQL;
SELECT COUNT(*) INTO :obscount
FROM &dsnms;
QUIT;
* Export all available files in the loop;
%Local D;
%DO D = 1 %TO &obscount;
* Print progress message;
sysecho "Progressing through &D of &obscount";
* Get table name;
PROC SQL;
SELECT COMPRESS(MEMNAME) INTO: Table
FROM &dsnms
WHERE rownum=&D;
QUIT;
* Extra spaces in file name are removed via cmpres call;
PROC EXPORT DBMS=CSV DATA=SASLIBWITHSTUFF.&Table
OUTFILE="/mystuff/%cmpres(&Table).csv";
RUN;
* Inform about succesful export;
sysecho "Created &Table..csv export file.";
%END;
%mend;
总结
换句话说,如果这样的话,我想修改 proc export
的行为来创建 NonExistingVar
在 Kepp =
中传递。当然,这会失败,因为 sashelp.class
没有 NonExistingVar
但这是我想要模仿的行为。
proc export data=sashelp.class (keep = name
sex
NonExistingVar)
outfile="/stuff/proc_test.csv"
dbms=csv
replace;
run;
如果您在某个地方有一个包含要导出的列列表的宏变量,您可以构建一个包含它们的视图,包括基础数据集中不存在的那些,然后导出视图.例如
%let keepcols = sex weight newcol;
data t_view /view = t_view;
if 0 then set sashelp.class;
if _n_ = 1 then call missing(of &keepcols);
set sashelp.class;
run;
if 0 then set xyz
是一个不错的小技巧,它允许您保留列顺序、长度和类型,而无需从第一个 set 语句中读取任何行。它避免了随后将变量设置为缺失值时的类型冲突——我们必须将它们初始化为 something 否则它们不会输出。第二个 set 语句将覆盖实际存在的变量的缺失值。
如果您查询元数据表以确定保留的哪些列存在,这可能会更有效一些,因此您只会加载那些列,但这在大多数情况下应该是合理的。
一个更懒惰的选项是暂时禁用与 keep 相关的错误和警告,例如:
%let keepcols = sex weight newcol;
%let dkricond = %sysfunc(getoption(dkricond)); /*Save for later*/
option dkricond = nowarn;
data t_view /view = t_view;
if 0 then set sashelp.class(keep = &keepcols); /*Normally this would trigger an error or warning*/
retain &keepcols;
set sashelp.class(keep = &keepcols);
run;
option dkricond = &dkricond; /*Restore original setting*/
为此,您需要有一个要输出的变量列表。因此,让我们假设您有一个带有该列表的宏变量。
%let varlist=varA varB varC ;
由于您正在编写 CSV 文件,因此您可以直接使用 DATA 步骤执行此操作,而避免使用 PROC EXPORT。在数据步骤中,如果您引用一个不存在的变量,那么 SAS 会很乐意为您创建一个空变量。
您可能需要有点创意才能添加 header 记录。这是一种使用 TRANWRD() 函数的方法,当您在每个变量名称之间只有一个 space 时,该函数有效。请注意,您可以使用 COMPBL() 来实现这一点。
%let varlist=Name Unknown Age ;
%let varlist=%sysfunc(compbl(&varlist));
data _null_;
file "/stuff/proc_test.csv" dsd ;
if _n_=1 then put "%sysfunc(tranwrd(&varlist,%str( ),%str(,)))" ;
set sashelp.class ;
put &varlist ;
run;
结果:
Name,Unknown,Age
Alfred,,14
Alice,,13
Barbara,,13
Carol,,14
Henry,,14
James,,12
Jane,,12
Janet,,15
Jeffrey,,13
John,,12
Joyce,,11
Judy,,14
Louise,,12
Mary,,15
Philip,,16
Robert,,12
Ronald,,15
Thomas,,11
William,,15
背景
我运行下面的宏在循环中导出了一些数据集。不幸的是,其中一些数据集有额外的变量。我的目的是以相同格式导出所有文件,其中 不存在的列作为空白提供 。
数据
这可以用以下数据集来说明。
dataA
varA varB
1 3
2 3
3 3
dataB
varA varB
9 4
9 4
9 4
dataC
varA varB varC
2 5 6
2 5 6
2 5 6
我希望我的 CSV 文件如下所示:
dataA.CSV
varA varB varC
1 3 .
2 3 .
3 3 .
dataB.CSV
varA varB varC
9 4 .
9 4 .
9 4 .
dataC.CSV
varA varB varC
2 5 6
2 5 6
2 5 6
宏
%macro export_data(dsnms);
* Get observations count;
PROC SQL;
SELECT COUNT(*) INTO :obscount
FROM &dsnms;
QUIT;
* Export all available files in the loop;
%Local D;
%DO D = 1 %TO &obscount;
* Print progress message;
sysecho "Progressing through &D of &obscount";
* Get table name;
PROC SQL;
SELECT COMPRESS(MEMNAME) INTO: Table
FROM &dsnms
WHERE rownum=&D;
QUIT;
* Extra spaces in file name are removed via cmpres call;
PROC EXPORT DBMS=CSV DATA=SASLIBWITHSTUFF.&Table
OUTFILE="/mystuff/%cmpres(&Table).csv";
RUN;
* Inform about succesful export;
sysecho "Created &Table..csv export file.";
%END;
%mend;
总结
换句话说,如果这样的话,我想修改 proc export
的行为来创建 NonExistingVar
在 Kepp =
中传递。当然,这会失败,因为 sashelp.class
没有 NonExistingVar
但这是我想要模仿的行为。
proc export data=sashelp.class (keep = name
sex
NonExistingVar)
outfile="/stuff/proc_test.csv"
dbms=csv
replace;
run;
如果您在某个地方有一个包含要导出的列列表的宏变量,您可以构建一个包含它们的视图,包括基础数据集中不存在的那些,然后导出视图.例如
%let keepcols = sex weight newcol;
data t_view /view = t_view;
if 0 then set sashelp.class;
if _n_ = 1 then call missing(of &keepcols);
set sashelp.class;
run;
if 0 then set xyz
是一个不错的小技巧,它允许您保留列顺序、长度和类型,而无需从第一个 set 语句中读取任何行。它避免了随后将变量设置为缺失值时的类型冲突——我们必须将它们初始化为 something 否则它们不会输出。第二个 set 语句将覆盖实际存在的变量的缺失值。
如果您查询元数据表以确定保留的哪些列存在,这可能会更有效一些,因此您只会加载那些列,但这在大多数情况下应该是合理的。
一个更懒惰的选项是暂时禁用与 keep 相关的错误和警告,例如:
%let keepcols = sex weight newcol;
%let dkricond = %sysfunc(getoption(dkricond)); /*Save for later*/
option dkricond = nowarn;
data t_view /view = t_view;
if 0 then set sashelp.class(keep = &keepcols); /*Normally this would trigger an error or warning*/
retain &keepcols;
set sashelp.class(keep = &keepcols);
run;
option dkricond = &dkricond; /*Restore original setting*/
为此,您需要有一个要输出的变量列表。因此,让我们假设您有一个带有该列表的宏变量。
%let varlist=varA varB varC ;
由于您正在编写 CSV 文件,因此您可以直接使用 DATA 步骤执行此操作,而避免使用 PROC EXPORT。在数据步骤中,如果您引用一个不存在的变量,那么 SAS 会很乐意为您创建一个空变量。
您可能需要有点创意才能添加 header 记录。这是一种使用 TRANWRD() 函数的方法,当您在每个变量名称之间只有一个 space 时,该函数有效。请注意,您可以使用 COMPBL() 来实现这一点。
%let varlist=Name Unknown Age ;
%let varlist=%sysfunc(compbl(&varlist));
data _null_;
file "/stuff/proc_test.csv" dsd ;
if _n_=1 then put "%sysfunc(tranwrd(&varlist,%str( ),%str(,)))" ;
set sashelp.class ;
put &varlist ;
run;
结果:
Name,Unknown,Age
Alfred,,14
Alice,,13
Barbara,,13
Carol,,14
Henry,,14
James,,12
Jane,,12
Janet,,15
Jeffrey,,13
John,,12
Joyce,,11
Judy,,14
Louise,,12
Mary,,15
Philip,,16
Robert,,12
Ronald,,15
Thomas,,11
William,,15