SAS循环数据集
我在库调用snap1中有多个表: 客户1、客户2、客户3等 我想生成一个循环,获取每个表中相同列的记录计数,然后将结果插入到不同的表中 我期望的输出是:SAS循环数据集,sas,Sas,我在库调用snap1中有多个表: 客户1、客户2、客户3等 我想生成一个循环,获取每个表中相同列的记录计数,然后将结果插入到不同的表中 我期望的输出是: Table Count cust1 5,000 cust2 5,555 cust3 6,000 我正在尝试,但它不起作用: %macro sqlloop(data, byvar); proc sql noprint; select &byvar.into:_values SEPARATED by '_' from %data.; q
Table Count
cust1 5,000
cust2 5,555
cust3 6,000
我正在尝试,但它不起作用:
%macro sqlloop(data, byvar);
proc sql noprint;
select &byvar.into:_values SEPARATED by '_'
from %data.;
quit;
data_&values.;
set &data;
select (%byvar);
%do i=1 %to %sysfunc(count(_&_values.,_));
%let var = %sysfunc(scan(_&_values.,&i.));
output &var.;
%end;
end;
run;
%mend;
%sqlloop(data=libsnap, byvar=membername);
*已更新*
将来,请发布日志,以便我们可以看到哪些具体不起作用。我可以在代码中看到一些问题,特别是在声明宏变量的地方,以及一个没有做任何事情的select
语句。以下是实现目标的另一个过程:
步骤1:将snap1
库中的所有客户数据集读取到宏变量中:
proc sql noprint;
select memname
into :total_cust separated by ' '
from sashelp.vmember
where upcase(memname) LIKE 'CUST%'
AND upcase(libname) = 'SNAP1';
quit;
步骤2:计算每个数据集中OB的总数,输出到永久表:
%macro count_obs;
%do i = 1 %to %sysfunc(countw(&total_cust) );
%let dsname = %scan(&total_cust, &i);
%let dsid=%sysfunc(open(&dsname) );
%let nobs=%sysfunc(attrn(&dsid,nobs) );
%let rc=%sysfunc(close(&dsid) );
data _total_obs;
length Member_Name $15.;
Member_Name = "&dsname";
Total_Obs = &nobs;
format Total_Obs comma8.;
run;
proc append base=Total_Obs
data=_total_obs;
run;
%end;
proc datasets lib=work nolist;
delete _total_obs;
quit;
%mend;
%count_obs;
如果永久表已经存在,则需要删除该表,但如果愿意,可以添加代码来处理该表
如果要获取特定列的未丢失观测值总数,请执行与上面相同的代码,但删除下面的3个%let
语句%let dsname=
,并将数据
步骤替换为:
data _total_obs;
length Member_Name $7.;
set snap1.&dsname end=eof;
retain Member_Name "&dsname";
if(NOT missing(var) ) then Total_Obs+1;
if(eof);
format Total_Obs comma8.;
run;
(更新:修复了步骤2中的%do循环) *已更新* 将来,请发布日志,以便我们可以看到哪些具体不起作用。我可以在代码中看到一些问题,特别是在声明宏变量的地方,以及一个没有做任何事情的
select
语句。以下是实现目标的另一个过程:
步骤1:将snap1
库中的所有客户数据集读取到宏变量中:
proc sql noprint;
select memname
into :total_cust separated by ' '
from sashelp.vmember
where upcase(memname) LIKE 'CUST%'
AND upcase(libname) = 'SNAP1';
quit;
步骤2:计算每个数据集中OB的总数,输出到永久表:
%macro count_obs;
%do i = 1 %to %sysfunc(countw(&total_cust) );
%let dsname = %scan(&total_cust, &i);
%let dsid=%sysfunc(open(&dsname) );
%let nobs=%sysfunc(attrn(&dsid,nobs) );
%let rc=%sysfunc(close(&dsid) );
data _total_obs;
length Member_Name $15.;
Member_Name = "&dsname";
Total_Obs = &nobs;
format Total_Obs comma8.;
run;
proc append base=Total_Obs
data=_total_obs;
run;
%end;
proc datasets lib=work nolist;
delete _total_obs;
quit;
%mend;
%count_obs;
如果永久表已经存在,则需要删除该表,但如果愿意,可以添加代码来处理该表
如果要获取特定列的未丢失观测值总数,请执行与上面相同的代码,但删除下面的3个%let
语句%let dsname=
,并将数据
步骤替换为:
data _total_obs;
length Member_Name $7.;
set snap1.&dsname end=eof;
retain Member_Name "&dsname";
if(NOT missing(var) ) then Total_Obs+1;
if(eof);
format Total_Obs comma8.;
run;
(更新:在步骤2中修复了%do循环)首先,如果您只需要观察的数量,您可以从没有任何循环的
dictionary.tables
或sashelp.vtable
中获得
proc sql;
select memname, nlobs
from dictionary.tables
where libname='SNAP1';
quit;
如果您没有做任何会导致逻辑观察数不同的事情(通常是proc sql中的删除),则可以检索行数
其次,如果您对有效响应的数量感兴趣,也有更简单的非循环方法
例如,给定您可以编写的用于确定表名的任何查询,我们可以将它们全部放在set
语句中,并在一个简单的数据步骤中进行计数
%let varname=mycol; *the column you are counting;
%let libname=snap1;
proc sql;
select cats("&libname..",memname)
into :tables separated by ' '
from dictionary.tables
where libname=upcase("&libname.");
quit;
data counts;
set &tables. indsname=ds_name end=eof; *9.3 or later;
retain count dataset_name;
if _n_=1 then count=0;
if ds_name ne lag(ds_name) and _n_ ne 1 then do;
output;
count=0;
end;
dataset_name=ds_name;
count = count + ifn(&varname.,1,1,0); *true, false, missing; *false is 0 only;
if eof then output;
keep count dataset_name;
run;
这类事情很少需要宏,像您正在编写的宏循环就更不需要了
如果确实要编写宏,更简单的方法是:
- 为一个数据集编写一次代码
- 将其包装在接受参数(数据集名称)的宏中
- 根据需要为该宏创建宏调用
%scan
和疑难解答难以调试的宏代码。你只写一次有效的东西,然后多次调用它
proc sql;
select cats('%mymacro(name=',"&libname..",memname,')')
into :macrocalls separated by ' '
from dictionary.tables
where libname=upcase("&libname.");
quit;
¯ocalls.;
假设您有一个宏,
%mymacro
,它可以对一个数据集执行任何您想要的计数。首先,如果您只需要观察的数量,您可以从没有任何循环的字典.tables
或sashelp.vtable
中轻松获得
proc sql;
select memname, nlobs
from dictionary.tables
where libname='SNAP1';
quit;
如果您没有做任何会导致逻辑观察数不同的事情(通常是proc sql中的删除),则可以检索行数
其次,如果您对有效响应的数量感兴趣,也有更简单的非循环方法
例如,给定您可以编写的用于确定表名的任何查询,我们可以将它们全部放在set
语句中,并在一个简单的数据步骤中进行计数
%let varname=mycol; *the column you are counting;
%let libname=snap1;
proc sql;
select cats("&libname..",memname)
into :tables separated by ' '
from dictionary.tables
where libname=upcase("&libname.");
quit;
data counts;
set &tables. indsname=ds_name end=eof; *9.3 or later;
retain count dataset_name;
if _n_=1 then count=0;
if ds_name ne lag(ds_name) and _n_ ne 1 then do;
output;
count=0;
end;
dataset_name=ds_name;
count = count + ifn(&varname.,1,1,0); *true, false, missing; *false is 0 only;
if eof then output;
keep count dataset_name;
run;
这类事情很少需要宏,像您正在编写的宏循环就更不需要了
如果确实要编写宏,更简单的方法是:
- 为一个数据集编写一次代码
- 将其包装在接受参数(数据集名称)的宏中
- 根据需要为该宏创建宏调用
%scan
和疑难解答难以调试的宏代码。你只写一次有效的东西,然后多次调用它
proc sql;
select cats('%mymacro(name=',"&libname..",memname,')')
into :macrocalls separated by ' '
from dictionary.tables
where libname=upcase("&libname.");
quit;
¯ocalls.;
假设您有一个宏,
%mymacro
,它可以对一个数据集进行任何您想要的计数。您能更好地解释一下您想要什么吗?示例输入和输出会有所帮助。在尝试创建宏之前,请确保您知道如何为特定情况编写代码。然后,您可以开始编写一个宏,为其他情况生成该代码。现在宏没有生成任何有效的SAS代码。该代码与结果有什么关系?它不会做任何与你所说的你想要的无关的事情。你能更好地解释你想要什么吗?示例输入和输出会有所帮助。在尝试创建宏之前,请确保您知道如何为特定情况编写代码。然后,您可以开始编写一个宏,为其他情况生成该代码。现在宏没有生成任何有效的SAS代码。该代码与结果有什么关系?它根本不会做任何与您所说的内容相关的事情。这是可行的,但表的名称不完全是cust1、cust2等。如何让代码打印出确切的名称?使用更通用的解决方案更新