在sas中使用do循环指定数据格式

时间:2018-08-07 20:43:08

标签: sas

我有一个大型数据文件,其数据格式如下:国家/地区,数据类型,year1month1至year2018month7。

使用proc导入读取数据并不适用于所有数据字段。我最终修改了SAS数据步骤代码,以确保数据格式正确。

但是,我在简化代码方面遇到了麻烦,也就是说,我希望do遍历所有年月。这样,我可以使用当前日期来确定文件的日期范围,并且用于创建Year / Month变量的代码不必在文件中重复100次。

data test;
infile 'abc.csv' delimiter = ',' MISSOVER DSD lrecl=32767 firstobs=2 ;

informat Country_Name $34. ;
do i = 1940 to 2018; 
    do j = 1 to 12; 
        informat _(i)M(j) best32.;
    end;
end;
informat Base_Year $1. ;

format Country_Name $34. ;
do i = 1940 to 2018; 
    do j = 1 to 12; 
        format _(i)M(j) best12.;
    end;
end;
format Base_Year $1. ;

input
Country_Name  $
do i = 1940 to 2018; 
    do j = 1 to 12; 
        _(i)M(j) $;
    end;
end;
Base_Year  $;
run;

2 个答案:

答案 0 :(得分:0)

这里有一些可行的方法。与您的方法最直接相关的翻译是使用宏语言。

您需要将这两个循环翻译成这样:

%do i = 1940 %to 2018; 
    %do j = 1 %to 12; 
        informat _&i.M&j. best32.;
    %end;
%end;

注意%。这也必须在宏中。您无法在正常的数据步骤代码中执行此操作。

我将其重写为使用如下宏:

%macro make_ym(startyear=, endyear=, separator=);
%local i j;
%do i = &startyear. %to &endyear.; 
    %do j = 1 %to 12; 
        _&i.&separator.&j.
    %end;
%end;
%mend make_ym;

data test;
infile 'abc.csv' delimiter = ',' MISSOVER DSD lrecl=32767 firstobs=2 ;

informat Country_Name $34. ;

informat %make_ym(startyear=1940,endyear=2018,separator=M) best32.;

informat Base_Year $1. ;

format %make_ym(startyear=1940,endyear=2018,separator=M) best12.;

format Base_Year $1. ;

input
Country_Name  $
%make_ym(startyear=1940,endyear=2018,separator=M)
Base_Year  $;
run;

由于您将它们声明为数字,因此我在输入的yMm位之后取出了$

答案 1 :(得分:0)

不要在PROC IMPORT生成的代码之后对数据步骤建模。它做了很多无用的事情,例如将格式和信息附加到不需要它们的变量上。

对于您的问题,您只需要一个简单的程序,如下所示:

data test;
   infile 'abc.csv' dsd dlm= ',' truncover firstobs=2 ;
   input Country_Name :$34. Y1940M01 .... Y2018M08 Base_Year :$1. ;
run;

现在,唯一棘手的部分是建立数字变量列表。如果列表足够小,则可以将其放入宏变量中。幸运的是,在这种情况下这不是问题,因为使用8个字符名称(YyyyyMmm)可以使数据步骤字符变量中的值超过300年。长度为10,800字节的变量应该可以容纳100年的月份名称。

因此,请首先运行此数据步骤。

data _null_;
  length names $10800 ;
  basedate = mdy(1,1,1940);
  lastdate = today();
  do i=0 to intck('month',basedate,lastdate);
    date=intnx('month',basedate,i);
    names=catx(' ',names,cats('Y',year(date),'M',put(month(date),Z2.)));
  end;
  call symputx('names',names);
run;

现在,您可以在INPUT语句中使用宏变量了。

data test;
   infile 'abc.csv' dsd dlm= ',' truncover firstobs=2 ;
   input Country_Name :$34. &names Base_Year :$1. ;
run;