我正在使用带有proc boxplot和proc报告的BY语句来为BY变量的每个级别创建一个绘图和一个表。按原样,代码打印所有图,然后打印所有表。我希望它打印绘图,然后打印By变量的每个级别的表(因此输出将在绘图和表之间交替)。有没有办法做到这一点?
这是我目前用于绘图和表格的代码 -
proc boxplot data=study;
plot Lead_Time*Study_ID/ horizontal;
by Project_Name;
format Lead_Time dum.;
run;
proc report data=study nowd;
column ID Title Contact Status Message Audience Priority;
by Project_Name;
run;
谢谢!!
答案 0 :(得分:1)
不幸的是,我不认为ODS(输出传送系统)可以交错程序的输出。您将需要使用宏来遍历所有变量,并为每个变量调用BOXPLOT和REPORT。
这样的事情:
%macro myreport();
%let byvars = A B C D;
%let n=4;
%do i=1 %to &n;
%let var = %scan(&byvars,&i);
proc something data=have(where=(byvar="&var"));
...;
run;
proc report data=have(where=(byvar="&var"));
....
run;
%end;
%mend;
%myreport();
显然,您需要根据自己的需要进行更改。 Stackoverflow上有很多例子。这是一个:looping over character values in SAS
答案 1 :(得分:1)
原则上可以使用PROC DOCUMENT
和ODS DOCUMENT
输出类型。这本身并不容易,但它有可能,并且比宏选项有一些优势,尽管我不确定是否足以推荐它的使用。但是,它值得探索。
首先,在2009年SAS全球论坛期间,Cynthia Zender的优秀教程Have It Your Way: Rearrange and Replay Your Output with ODS DOCUMENT主要指导(包括,巧合地,使用相同的数据集!)。她最初描述了一种这样做的GUI方法,但后来在代码中对它进行了解释,这对于这类事情来说显然是优越的。凯文史密斯在ODS DOCUMENT From Scratch中涵盖了与2012年的SGF相似的基础,尽管辛西娅的论文在这里更适用(因为她涵盖了确切的主题)。
首先,您需要生成所有结果。这里的订单并不重要。 我生成了一个SASHELP.PRDSALE样本,该样本按国家/地区进行了适当排序。
proc sort data=sashelp.prdsale out=prdsale;
by country;
run;
然后,我们生成一些表格;一个proc手段和一个sgplot。请注意标题使用#BYVAL1
来确保包含标题 - 否则我们会丢失过程中的有用标签!
title "#BYVAL1 Report";
ods _all_ close;
ods document name=work.mydoc(write);
proc means data=prdsale sum;
by country;
class quarter year;
var predict;
run;
proc sgplot data=prdsale;
by country;
vbar quarter/response=predict group=year groupdisplay=cluster;
run;
ods document close;
ods preferences;
现在,我们有一些错误,但可以用于你真正想要的东西。你可以使用Cynthia或Kevin的论文中的技巧来详细研究这个问题。现在我只是为了这个目的而进入你需要的东西。
它现在像这样组织,想象一个文件夹树:
\ REPORT \手段\ COUNTRY \
我们需要的是:
\ REPORT \ COUNTRY \ MEANS
这很容易做到。这样做的代码如下。显然,对于生产过程,这将更好地自动化;给定输入数据集,生成此代码应该是微不足道的。请注意,BYVAL按值递增,因此CANADA为1和4,德国为2和5,美国为3和6。
proc document name=work.mydoc_new(write);
make CANADA, GERMANY, USA; *make the lower level folders;
run;
dir ^^; *Go to the bottom level, think "cd .." in unix/windows;
dir CANADA; *go to Canada folder;
dir; *Notes to the Listing destination where we are, not that important;
copy \work.mydoc\Means#1\ByGroup1#1\Summary#1 to ^; *copy that folder from orig doc to here;
copy \work.mydoc\SGPlot#1\ByGroup4#1\SGPlot#1 to ^; *^ being current directory, like '.' in unix/windows;
*您也可以复制\ ByGroup1#1和\ Bygroup4#1而不使用树的最后一级。这样会产生略微不同的结果(表中会包含更多的文字),所以请根据您的期望进行调整。
**德国和美国也是如此。请注意,这是易于自动化的部分! dir ^^; 德国德里; DIR; copy \ work.mydoc \ Means#1 \ ByGroup2#1 \ Summary#1 to ^; copy \ work.mydoc \ SGPlot#1 \ ByGroup5#1 \ SGPlot#1 to ^;
dir ^^;
dir USA;
dir;
copy \work.mydoc\Means#1\ByGroup3#1\Summary#1 to ^;
copy \work.mydoc\SGPlot#1\ByGroup6#1\SGPlot#1 to ^;
run;
quit; *this is one of those run group procedures, need a quit;
现在,您只需要replay
该文档即可以正确的方式解决问题。
proc document name=mydoc_new;
replay;
run;
quit;
田田,你有你想要的东西。
答案 2 :(得分:1)
如果您要按值运行一次触发,那很容易。创建一个宏只运行一个实例,然后使用proc sql
为每个实例创建一个调用。这是完全动态的,可以很容易地调整,以允许其他选项,如变量,级别等多个。
给出单个值:
*Macro that runs it once;
%macro run_reports(project_name=);
title "Report for &project_name.";
proc boxplot data=study;
plot Lead_Time*Study_ID/ horizontal;
where Project_Name="&project_name.";
format Lead_Time dum.;
run;
proc report data=study nowd;
column ID Title Contact Status Message Audience Priority;
where Project_Name="&project_name.";
run;
%mend run_Reports;
*SQL pull to create a list of macro calls;
proc sql;
select distinct cats('%run_Reports(project_name=',project_name,')')
into :runlist separated by ' '
from study;
quit;
&runlist.;
打开options symbolgen;
以查看运行列表的外观,或查看输出窗口(或9.3+中的结果窗口)。在生产中运行此功能时,请将noprint
添加到proc sql
以避免生成该表。