【问题标题】:specifying data informat using do loops in sas在 sas 中使用 do 循环指定数据信息
【发布时间】:2019-01-15 00:51:55
【问题描述】:

我有一个大型数据文件,其中包含以下格式的数据:国家、数据类型、year1month1 到 year2018month7。

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

但是,我在简化代码时遇到了麻烦,即我希望一个 do 循环能够遍历所有年份和月份。这样,我可以使用当前日期来确定文件的日期范围,并且创建年/月变量的代码不必在文件中重复 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;

【问题讨论】:

    标签: sas


    【解决方案1】:

    这里有一些可行的方法。最直接转化为您的方法是使用宏语言。

    你需要把这两个循环翻译成这样:

    %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 位之后取出了 $,因为您将它们声明为数字。

    【讨论】:

      【解决方案2】:

      不要在 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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多