如何在SAS中检测数据集中有多少个观测值(如果是空的话)?
我想知道是否有一种方法可以检测数据集是否为空,即它没有观测值。 或者换句话说,如何获得特定数据集中的观测数量 这样我就可以写一个If语句来设置一些条件如何在SAS中检测数据集中有多少个观测值(如果是空的话)?,sas,Sas,我想知道是否有一种方法可以检测数据集是否为空,即它没有观测值。 或者换句话说,如何获得特定数据集中的观测数量 这样我就可以写一个If语句来设置一些条件 谢谢。使用PROC-SQL很容易。进行计数并将结果放入宏变量中 proc sql noprint; select count(*) into :observations from library.dataset; quit; 有很多不同的方法,我倾向于使用带有open()和attrn()的宏函数。下面是一个简单的例子,在大多数情况下效果都很好
谢谢。使用PROC-SQL很容易。进行计数并将结果放入宏变量中
proc sql noprint;
select count(*) into :observations from library.dataset;
quit;
有很多不同的方法,我倾向于使用带有
open()
和attrn()
的宏函数。下面是一个简单的例子,在大多数情况下效果都很好。如果您要处理数据视图或更复杂的情况,如数据集上有标记为删除的记录或活动where子句,那么您可能需要更健壮的逻辑
%macro nobs(ds);
%let DSID=%sysfunc(OPEN(&ds.,IN));
%let NOBS=%sysfunc(ATTRN(&DSID,NOBS));
%let RC=%sysfunc(CLOSE(&DSID));
&NOBS
%mend;
/* Here is an example */
%put %nobs(sashelp.class);
下面是@cmjohns谈论的更完整的示例。如果为空,则返回0;如果缺少,则返回1;并且可以选择处理已删除的观察结果和where子句(请注意,在非常大的数据集上使用where子句可能会使宏花费很长时间) 用法说明:
%macro nobs(iDs=, iWhereClause=1, iNobsType=nlobsf, iVerbose=1);
%local dsid nObs rc;
%if "&iWhereClause" eq "1" %then %do;
%let dsID = %sysfunc(open(&iDs));
%end;
%else %do;
%let dsID = %sysfunc(open(&iDs(where=(&iWhereClause))));
%end;
%if &dsID %then %do;
%let nObs = %sysfunc(attrn(&dsID,nlobsf));
%let rc = %sysfunc(close(&dsID));
%end;
%else %do;
%if &iVerbose %then %do;
%put WARNING: MACRO.NOBS.SAS: %sysfunc(sysmsg());
%end;
%let nObs = -1;
%end;
&nObs
%mend;
%put %nobs(iDs=sashelp.class);
%put %nobs(iDs=sashelp.class, iWhereClause=height gt 60);
%put %nobs(iDs=this_dataset_doesnt_exist);
此宏将返回数据集中的观察数。如果数据集不存在,则返回-1。我不建议将其用于ODBC libnames,只对SAS表使用
参数:
- iDs—要检查的
libname.dataset
- Iwhere子句(可选)-适用的where子句
- iNobsType(可选)NOBS或
。有关说明,请参阅NLOBSF
%macro nobs(iDs=, iWhereClause=1, iNobsType=nlobsf, iVerbose=1);
%local dsid nObs rc;
%if "&iWhereClause" eq "1" %then %do;
%let dsID = %sysfunc(open(&iDs));
%end;
%else %do;
%let dsID = %sysfunc(open(&iDs(where=(&iWhereClause))));
%end;
%if &dsID %then %do;
%let nObs = %sysfunc(attrn(&dsID,nlobsf));
%let rc = %sysfunc(close(&dsID));
%end;
%else %do;
%if &iVerbose %then %do;
%put WARNING: MACRO.NOBS.SAS: %sysfunc(sysmsg());
%end;
%let nObs = -1;
%end;
&nObs
%mend;
%put %nobs(iDs=sashelp.class);
%put %nobs(iDs=sashelp.class, iWhereClause=height gt 60);
%put %nobs(iDs=this_dataset_doesnt_exist);
用法示例:
%macro nobs(iDs=, iWhereClause=1, iNobsType=nlobsf, iVerbose=1);
%local dsid nObs rc;
%if "&iWhereClause" eq "1" %then %do;
%let dsID = %sysfunc(open(&iDs));
%end;
%else %do;
%let dsID = %sysfunc(open(&iDs(where=(&iWhereClause))));
%end;
%if &dsID %then %do;
%let nObs = %sysfunc(attrn(&dsID,nlobsf));
%let rc = %sysfunc(close(&dsID));
%end;
%else %do;
%if &iVerbose %then %do;
%put WARNING: MACRO.NOBS.SAS: %sysfunc(sysmsg());
%end;
%let nObs = -1;
%end;
&nObs
%mend;
%put %nobs(iDs=sashelp.class);
%put %nobs(iDs=sashelp.class, iWhereClause=height gt 60);
%put %nobs(iDs=this_dataset_doesnt_exist);
结果
19
12
-1
安装
我建议设置一个宏并将其放置在自动调用位置 当我们有大数据集时,Proc-sql效率不高。虽然使用ATTR是一种很好的方法,但这可以在基本sas中实现,但下面是一个高效的解决方案,它可以通过读取一行来提供数十亿行的OB数:
data DS1;
set DS nobs=i;
if _N_ =2 then stop;
No_of_obs=i;
run;
诀窍是即使数据集为空也要生成输出
data CountObs;
i=1;
set Dataset_to_Evaluate point=i nobs=j; * 'point' avoids review of full dataset*;
No_of_obs=j;
output; * Produces a value before "stop" interrupts processing *;
stop; * Needed whenever 'point' is used *;
keep No_of_obs;
run;
proc print data=CountObs;
run;
上面的代码是我发现的最简单的方法,即使在数据集为空的情况下也可以生成观察数。我听说NOB可能很棘手,但上述方法适用于简单的应用程序。稍有不同的方法:
proc contents data=library.dataset out=nobs;
run;
proc summary data=nobs nway;
class nobs;
var delobs;
output out=nobs_summ sum=;
run;
这将为您提供一个具有一个观测值的数据集;变量nobs的值等于数据集中的观测数,即使它是0。我想我已经在尝试用这么多的答案重新发明轮子了。但我确实看到一些其他方法试图从实际数据集计数——对于大型数据集,这可能需要很长时间。以下是一种更有效的方法:
proc sql;
select nlobs from sashelp.vtable where libname = "library" and memname="dataset";
quit;
谢谢Laurent的快速回答。它似乎非常有用。Hi Laurent-这对于小数据集是可以的,但是对于大数据集,它可能需要相当长的时间来执行,因为它必须读取每个观察值,而不仅仅是查看表的元数据。请参阅下面的一些其他答案,以获得更有效的方法。
count(var_name)
读取每个观察值,但count(*)
不读取。@Ryan如果这样做会很好,但不幸这是错误的。尽管如此,谢谢你,John。我稍后会尝试。不严格相关。但我有时觉得这太复杂了。在R中,相关的命令是nrow(data.frame1)@xiaodai,这就是为什么您应该使用宏自动调用库或proc fcmp
,或两者兼用的原因。然后将代码简化为最后一部分:%nobs(sashelp.class)
Hi Rob,我想您也是SAS的高级用户。当我理解代码时,我会尝试一下。无论如何,还是谢谢你。罗伯特,你知道如何修改以确定是否既没有obs也没有VAR吗?在这种情况下返回1。我尝试过使用各种attrn选项,但找不到方法。@米尔卡,当然,测试变量数量所需的代码是%let nVars=%sysfunc(attrn(&dsID,nVars))代码>。这行代码需要在运行%let nobs
语句的地方执行。我将把其余的逻辑留给您,让您尽可能地了解您希望返回的值。+1对于不使用那些可怕的%
符号的解决方案,请注意,在某些情况下,nobs
不起作用。您需要将output语句移到set语句之前,以允许它处理零观测值的输入数据集。实际上,您需要使用NLOB而不是NOBS。这个变量考虑了删除的观测值(DELOB)的数量。很好的添加。如果您不想使用sashelp.vtable,还可以使用dictionary.tables
。我记不起确切的情况,但有一次我遇到一个情况,其中一个用了将近30秒的时间跑,而另一个则是瞬间。例如,procsqlnoprint;从dictionary.tables中选择nlobs,其中libname='SASHELP'和memname='CLASS';退出代码>