SAS中的数据透视表

时间:2017-06-05 16:54:45

标签: sas pivot-table enterprise-guide

数据如下:

YEAR    MONTH   ID1 ID2 FIELD   FIELD_DESC
2017    4   123 2222    FFF red1
2017    4   123 2222    FFG red2
2017    4   224 2221    XYZ green1
2017    4   225 1234    TYU blue5

并且所需的输出是

YEAR    MONTH   ID1 ID2 blue5   green1  red1    red2
2017    4   123 2222    0   0   1   1
2017    4   224 2221    0   1   0   0
2017    4   225 1234    1   0   0   0

在SQL服务器上,我曾经运行以下命令:

select year, month, id1, id2, [field1], [field2] .... [fieldn]
from (select year, month, id1, id2, field, field_desc from source_table) P
Pivot (count(field) for field_desc in ([field1], [field2] .... [fieldn])) Pvt

以上将按年,月,id1,id2给出每个可能描述的字段数。

我试图将其转换为SAS。

一种方法是条件总和

proc sql;
create table aggr_table as 
select year, month, id1, id2,
sum(case when field_desc = 'field1' then 1 else 0 end) as field1
...
sum(case when field_desc = 'fieldn' then 1 else 0 end) as fiendn
from source_table 
group by year, month, id1, id2;
quit;

我尝试做的第二种方式是

proc sort data = source_table
 by year descending month descending id1 descending id2;
run;

data table_aggr (keep year month id1 id2 field1 .... fieldn);
set source_table
retain field1
....
fieldn 0);

if field_desc = 'field1' then do;
field1 = field1 +1;
end;
....
if field_desc = 'fieldn' then do;
fieldn = fieldn + 1;
end;

if last.id2 then 
output;
by year month id1 id2;
run;

但第二种方式似乎不起作用

  

错误:BY变量未在数据集上正确排序   WORK.SOURCE_TABLE

我的问题: 1)到目前为止我的谷歌搜索似乎表明偏好在数据步骤而不是proc sql步骤中进行这种数据操作,是否有特别的优势?

2)我在数据步骤中做错了什么?

3)有没有更好的方法在帖子顶部复制SQL代码?与SQL原始版本相比,我所看到的两种SAS选项看起来都相当笨拙。

谢谢 本

2 个答案:

答案 0 :(得分:2)

这就是SAS为PROC提供的功能。

大多数过程中的Off语句(CLASS,特别是proc means)允许您按各种级别进行汇总。例如:

proc tabulate

或者:

proc means data=sashelp.class;
  var height weight;  *the numeric variables you are calculating with;
  class age sex;      *the grouping variables;
  types () age sex age*sex;   *the interactions you want - or use NWAY or WAYS;
run;

根据proc的不同,您可以通过多种方式获取此信息。许多人都有proc tabulate data=sashelp.class; var height weight; *numeric variables to calculate with; class age sex; *grouping variables; tables (all age sex age*sex),(height weight)*n; run; 个选项或out语句(例如outputPROC MEANS语句来执行此操作)。此外,OUTPUT可让您以表格形式访问屏幕上打印的所有内容。

ODS OUTPUT

- 或 -

ods output table=want;
proc tabulate data=sashelp.class;
  var height weight;
  class age sex;
  tables (all age sex age*sex),(height weight)*n;
run;
ods output close;

答案 1 :(得分:1)

您可以使用PROC SUMMARY为您计算,然后使用PROC TRANSPOSE将计数转换为变量而不是观察值。如果您只是直接执行此操作,那么对于未显示的组合,您将获得缺失值而不是零。您可以对文件进行后处理,以使用零替换缺少的计数。或者使用下面的方法构建一个CLASSDATA表以提供给PROC SUMMARY,以确保在转置之前包含所有零。

proc sql noprint ;
 create table classdata as
 select *
 from (select distinct year,month,id1,id2 from have) a
    , (select distinct field_desc from have) b
 ;
quit;
proc summary data=have nway classdata=classdata exclusive ;
  class year month id1 id2 field_desc ;
  output out=counts ;
run;
proc transpose data=counts out=want(drop=_name_);
  by year month id1 id2 ;
  id field_desc ;
  var _freq_;
run;

你可以让PROC SQL直接使用一些棘手的SQL生成完整的排名计数。将数据与id变量值的完整列表组合,并计算两个id变量匹配的次数。

proc sql noprint ;
 create table counts as
 select year,month,id1,id2
      , b.field_desc
      , sum(a.field_desc=b.field_desc) as count
 from have a
    , (select distinct field_desc from have) b
 group by year,month,id1,id2,b.field_desc
 order by year,month,id1,id2,b.field_desc
 ;
quit;

生成SQL很简单。如果派生变量的数量很小,那么只需将代码生成为宏变量。 (如果列表很大,则使用数据步骤生成代码,使用call execute()或将其写入文件并使用%include运行它。)

proc sql noprint ;
 select distinct
 catx(' '
     ,'sum(field_desc ='
     ,quote(trim(field_desc))
     ,') as'
     ,nliteral(field_desc)
     )
   into :code separated by ','
   from have
 ;
 create table want as
   select year, month, id1, id2
        , &code
   from have
   group by year, month, id1, id2
  ;
quit;

如果您想在数据步骤中执行此操作,请查看使用HASH对象来收集数据。然后使用PROC TRANSPOSE或代码生成技术(如上面的SQL中那样)从观察变换到变量。