【问题标题】:How can I peform same datastep across many variables in SAS?如何在 SAS 中跨多个变量执行相同的数据步骤?
【发布时间】:2015-07-30 18:08:15
【问题描述】:

我的数据看起来像这样,并且有 500 个带有目标的变量:

var1 var2 var3 var4 ... var500  target

变量的名称不像上面那样连续,所以我认为我不能使用像var1:var500 这样的东西。我想遍历变量来创建图表。有些变量是连续的,有些是名义变量。

for var1 through var500
   if nominal then create graphtypeA var[i] * target
   else if continous then create graphtypeB var[i] * target
end;

我可以轻松创建第二个表,其中包含要检查的数据类型。数组似乎对执行循环变量的任务很有用。比如:

data work.mydata;
   set archive.mydata;
   array myarray{501]  myarray1 - myarray501
   do i=1 to 500;
     proc sgpanel;
     panelby myarray[501];
     histogram myarray[i];
   end;     
run;

但这不起作用,它不会检查它是什么类型的变量。如果我们假设我有另一个具有 varname 和 vartype(连续,名义)的 sas.dataset,我如何循环创建给定 vartype 的所需图形?提前致谢。

【问题讨论】:

  • 您想要 500 个单独的 SGPLOT,还是在一个地块中有 500 个?
  • 单独的地块。进行双变量分析。
  • 我现在没有时间回答 - 但请查看“数据驱动编程”,这就是您想要做的。稍后会完整回答,如果没有其他人这样做。

标签: sas datastep


【解决方案1】:

基本上,您需要循环一些变量,应用一些逻辑来确定变量类型,然后根据变量类型产生输出。虽然有很多方法可以解决这个问题,但一种解决方案是将变量选择为宏变量,循环遍历这个变量“列表”(不是正式的数据结构),并使用宏控制逻辑为数字和字符指定不同的子例程变量。

我将使用 sashelp.cars 数据集进行说明。在此示例中,变量 origin 是您的“目标”变量,变量 Make、Type、Hourpower 和 Cylinders 是数字和字符变量。

* get some data;

data set1 (keep = Make Type Origin Horsepower Cylinders);
 set sashelp.cars;
run;

* create dataset of variable names and types;

proc contents data = set1
out = vars
noprint;
run;

* get variable names and variable types (1=numeric, 2=character)
* into two macro variable "lists" where each entry is seperated
* by a space;

proc sql noprint;
select  name, type
into :varname separated by ' ', :vartype separated by ' '
from vars
where name <> "Make";
quit; 

* put the macro variables to the log to confirm they are what
* you expect

%put &varname;
%put &vartype;

现在,使用宏循环遍历宏变量列表中的值。 countw 函数计算变量的数量,并使用这个数字作为循环迭代器的限制。 scan 函数通过其在相应宏变量列表中的相对位置读取每个变量名称和类型。然后对每个变量的类型进行评估,并根据它是字符还是数字生成图。在此示例中,为数值变量生成了带有密度图的直方图,为字符变量生成了频率计数条形图。

循环逻辑是通用的,Proc sgpanelProc sgplot cab 可以修改或替换为其他所需的数据步处理或程序。

* turn on options that are useful for 
* macro debugging, turn them off 
* when using in production;

options mlogic mprint symbolgen;

%macro plotter;
  %do i = 1 %to %sysfunc(countw(&varname));
        %let nextvar = %scan(&varname, &i, %str( ));
        %let nextvartype = %scan(&vartype, &i, %str( ));

        %if &nextvartype. = 1 %then %do;
          proc sgpanel data=set1 noautolegend;
            title "&nextvar. Distribution";
            panelby Origin;
            histogram &nextvar.;
            density &nextvar.;
            run;    
        %end;

        %if &nextvartype. = 2 %then %do;
          proc sgplot data=set1;
                    title "&nextvar. Count by Origin";
                    vbar &nextvar. /group= origin;
          run;  
        %end;
  %end;
%mend plotter;

*call the macro;
%plotter;

【讨论】:

  • 它似乎运行正确...但图形不打印到 ods 图形设备。我正在打印为 pdf,但没有打印任何内容。我应该在哪里放置 ods 图形选项以将输出打印为 pdf?
  • 可以在宏内部或外部添加 ods 选项。要生成单个文件,请将ods pdf file = "filepath\filename.pdf"; 添加到%macro plotter; 之后的行,并将ods pdf close; 添加到%mend plotter 之前的行
  • 这是我有它的地方,但我有另一个错字。然而,这段代码就像一个魅力......谢谢!
【解决方案2】:

不幸的是,不可能以您在此处建议的方式在数据步骤之外使用数组,至少不能以任何非常有效的方式。但是,您可以使用很多选项。一种方法是只调用一次您的图形处理程序并告诉它绘制数据集中的每个数字变量,例如像这样:

proc univariate data = sashelp.class;
    var _NUMERIC_;
    histogram;
run;

如果您要绘制的相同类型的变量在数据集的列顺序中相邻,您可以使用双破折号列表,例如

proc univariate data = sashelp.class;
    var age--weight;
    histogram;
run;

一般来说,您应该避免为每个变量单独调用 procs 或运行数据步骤 - 只调用一次并一次性处理所有内容几乎总是更有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-17
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多