SAS-Creating Panel由几个数据集组成

时间:2017-07-24 11:57:16

标签: sas panel

假设有十个数据集具有相同的结构:日期和价格,特别是它们具有相同的时间段但价格不同

 date       price
 20140604    5
 20140605    7
 20140607    9

我想将它们组合起来并创建一个面板数据集。由于每个数据集中没有名称,因此我尝试在每个数据中添加一个新变量name,然后将它们组合起来。

以下代码用于将name变量添加到每个数据集

%macro name(sourcelib=,from=,going=); 
proc sql noprint;  /*read datasets in a library*/
  create table mytables as
  select *
  from dictionary.tables
  where libname = &sourcelib
  order by memname ;

  select count(memname) 
  into:obs 
  from mytables;

  %let obs=&obs.;

  select memname
  into : memname1-:memname&obs.
  from mytables;
quit;

  %do i=1 %to &obs.;

  data 
  &going.&&memname&i;
  set
  &from.&&memname&i;
 name=&&memname&i;
  run;
%end;
%mend;

那么,这种策略是否正确?是否有不同的方法来创建面板数据?

3 个答案:

答案 0 :(得分:2)

有两种方法可以设置重复测量数据。您可以使用代码将创建的TALL方法。这通常是最灵活的。另一种是宽格式,每个PRICE存储在不同的变量中。这通常不太灵活,但对于某些分析可能更容易。

您可能不需要使用宏代码甚至代码生成来组合10个数据集。您可能会发现只键入10个数据集名称比编写复杂代码以从元数据中提取名称更容易。因此,像这样的数据步骤将允许您在SET语句中列出任意数量的数据集,并使用membername作为区分源数据集的新PANEL变量的值。

data want ;
  length dsn $41 panel $32 ;
  set in1.panel1 in1.panela in1.panelb indsname=dsn ;
  panel = scan(dsn,-1,'.') ;
run;

如果您的数据集名称遵循可以在SET语句中用作成员列表的模式,那么代码更容易编写。因此,您可以拥有一个带有数字后缀的名称列表。

  set in1.panel1-in1.panel10 indsname=dsn ;

或者所有名称都以特定前缀开头。

  set in1.panel:  indsname=dsn ;

如果不同的面板是相同的日期,那么宽幅面可能更容易?然后,您可以按DATE合并数据集并重命名各个PRICE变量。这样就生成了一个如下所示的数据步骤:

data want ;
   merge in1.panel1 (rename=(price=price1))
         in1.panel2 (rename=(price=price2))
         ...
   ;
   by date;
run;

或者将BY语句添加到生成TALL数据集的数据集然后将其转换为WIDE格式会更容易。

data tall;
  length dsn $41 panel $32 ;
  set in1.panel1 in1.panela in1.panelb indsname=dsn ;
  by date ;
  panel = scan(dsn,-1,'.') ;
run;
proc transpose data=tall out=want ;
  by date;
  id panel;
  var price ;
run;

答案 1 :(得分:1)

我无法评论SQL代码,但策略是正确的。为每个数据集添加一个名称,然后使用PANELBY语句在名称上面板。

答案 2 :(得分:1)

这是实现您所需要的有效方式。

.语法的宏之间需要2 library.data。第一个.用于连接。第二个显示为.

我假设你想要将所有这些数据集附加在一起。你可以添加

data &going..want;
set
  %do i=1 %to &obs;
      &from..&&memname&i
  %end;
;
run;

您可以组合添加名称的循环和数据步骤,如下所示:

data &going..want;
set
  %do i=1 %to &obs;
      &from..&&memname&i (in=d&i)
  %end;
;
%do i=1 %to &obs;
   if d&i then
      name = &&memname&i;
%end;
run;