【问题标题】:How to get do loop in SAS to work with date values?如何让 SAS 中的循环处理日期值?
【发布时间】:2018-02-13 09:27:30
【问题描述】:

我有一个包含 4 年数据(2014-2017)的数据集。 我想给每个观察结果一个包含来自 if 标准的 E、E/F 或 F 的周期变量。

我通过在数据步骤中每年重复我的代码来让它工作:

新数据; 旧的;

format period $10.;

if year=2014 then do;
    if start<'01feb2014'd and end<='01mar2014'd then period='E'; 
    else if start<'01feb2014'd and end>'01mar2014'd then period='E/F'; 
    else if start>='01feb2014'd then period='F';
end;
if year=2015 then do;
    if start<'01feb2015'd and end<='01mar2015'd then period='E'; 
    else if start<'01feb2015'd and end>'01mar2015'd then period='E/F'; 
    else if start>='01feb2015'd then period='F';
end;

if year=2016 then do;
    if start<'01feb2016'd and end<='01mar2016'd then period='E'; 
    else if start<'01feb2016'd and end>'01mar2016'd then period='E/F'; 
    else if start>='01feb2016'd then period='F';
end;
if year=2017 then do;
    if start<'01feb2017'd and end<='01mar2017'd then period='E'; 
    else if start<'01feb2017'd and end>'01mar2017'd then period='E/F'; 
    else if start>='01feb2017'd then period='F';
end;

运行;

但我想通过使用 af do 循环来更智能地编写代码。 我试过这个:

新数据; 旧的;

format period $10.;

do i=0 to 3;
    if year=(2014+i) then do;

        if start<'01feb(2014+i)'d and end<='01mar(2014+i)'d then period='E'; 
        else if start<'01feb(2014+i)'d and end>'01mar(2014+i)'d then period='E/F'; 
        else if start>='01feb(2014+i)'d then period='F';
    end;

end;

运行;

但这并不能给出 2015-2017 年的正确结果。

我也试过这个:

新数据; 旧的;

format period $10.;

do i=2014 to 2017;
    if year=(i) then do;

        if start<'01feb(i)'d and end<='01mar(i)'d then period='E'; 
        else if start<'01feb(i)'d and end>'01mar(i)'d then period='E/F'; 
        else if start>='01feb(i)'d then period='F';
    end;

end;

运行;

但是代码连运行都跑不了?

我错过了什么??

亲切的问候。

【问题讨论】:

    标签: loops date if-statement sas


    【解决方案1】:

    您可以使用MDY(3,1, 2017); 从整数创建日期。您还可以使用函数INTNX('month',dt,12,'END') + 1; 将日期dt 加12 个月,然后到达月末并加1 到达下个月的月初。

    所以如果我没记错的话,下面的代码应该可以工作。

    format period $10.;
    
    do i=2014 to 2017;
        if year=(i) then do;
    
            if start<MDY(2,1, i) and end<=MDY(3,1, i) then period='E'; 
            else if start<MDY(2,1, i) and end>MDY(3,1, i) then period='E/F'; 
            else if start>=MDY(2,1, i) then period='F';
        end;
    
    end;
    

    【讨论】:

    • 这给了我我想要的——以及正确的结果。非常感谢。
    【解决方案2】:

    我不明白为什么您需要一个 DO 循环来处理该数据。不同年份有不同的观察结果。您可以使用 MDY() 函数从单独的月、日和年值构建日期。

    data new;
      set old;
      length period $10;
      if start<mdy(2,1,year) and end<=mdy(3,1,year) then period='E'; 
      else if start<mdy(2,1,year) and end>mdy(3,1,year) then period='E/F'; 
      else if start>=mdy(2,1,year) then period='F'; 
      else period=' ';
    run;
    

    如果 YEAR 变量不在您的数据中,并且您希望将数据复制到 2014 年到 2017 年的每一年的单独观察中,那么您可以添加一个 DO 循环,其中包含一个 OUTPUT 语句。

    data new;
      set old;
      length year 8 period $10;
      do year=2014 to 2017;
        if start<mdy(2,1,year) and end<=mdy(3,1,year) then period='E'; 
        else if start<mdy(2,1,year) and end>mdy(3,1,year) then period='E/F'; 
        else if start>=mdy(2,1,year) then period='F'; 
        else period=' ';
        output;
      end;
    run;
    

    P.S. FORMAT 语句用于附加如何显示变量的特殊指令,但 SAS 不需要特殊指令来显示字符变量。如果您想在开始在数据步骤代码中使用它之前定义一个新变量,您可以使用LENGTHATTRIB 语句。

    【讨论】:

    • 感谢您的帮助。我只是想生成一些没有那么多复制的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多