【问题标题】:SAS: Using PROC SQL to write a date variable into a SAS datasetSAS:使用 PROC SQL 将日期变量写入 SAS 数据集
【发布时间】:2017-08-19 15:24:09
【问题描述】:

我正在编写 SAS 中的一段代码,旨在提取给定时间序列数据列中的最后一个非空值及其相应的日期,然后将它们插入到新数据集中。 SQL 似乎是迄今为止最简单的方法,所以这就是我一直在使用的方法。

我正在读取的数据集称为 rtchg1,它是从早期代码中的 .xlsx 电子表格导入的。它由一个日期变量和一堆时间序列变量组成。

data rtchg1;
set rtchg1;
where date between '1FEB1959'd and '1OCT1998'd;
run;

我要写入的表是 Forecasts,用一些简单的 SQL 创建:

PROC SQL ;
    CREATE TABLE Forecasts
    (Date date,      
     Forecast num);
run;    

我之前对“日期”进行了更复杂的格式化,并遇到了同样的问题。如果我在这里做错了什么,请告诉我,任何关于如何改进我的代码的建议都非常感谢。

最后我一直在开发以下宏来提取数据:

%macro scoreprep(readtable,datevar,writetable); 
%do i=1 %to 3;

    %let currentvar=%scan(&periods,&i);

    proc sql;
        select &datevar, &currentvar into :date1, :LEI
        from &readtable
        where &currentvar is not null
        having &datevar=max(&datevar);

        insert into &writetable (Date, Forecast)
            values ("&date1"d, &LEI);
    quit;

%end;
%mend;

%scoreprep(rtchg1,date,Forecasts); 

现在它只从 1 变为 3,以便在没有太多等待时间的情况下对其进行测试,等等。这里的一切似乎都完美无缺,除了将日期变量插入表中。当我删除日期变量并仅输入 &LEI 时,它会将其写入预测表而没有任何问题。当我按原样运行代码时,出现以下错误:

错误:无效的日期/时间/日期时间常数“10/01/1968”d.

不确定从这里开始,无论我在哪里尝试转换宏变量的格式,似乎都没有正常工作。建议将不胜感激。此外,如果您在我的代码中看到任何您不喜欢的内容,请随时批评。我确实知道在 Excel 中执行此操作的更简单方法,但这种方法更有趣:)

【问题讨论】:

    标签: sql macros sas proc-sql


    【解决方案1】:

    由于您要将值提取到字符串中,因此您需要告诉 SAS 如何将该字符串转换回日期。明确说明您是如何进行转换的。首先生成宏变量,然后生成 VALUES() 语句。因此,如果 Forecast 是一个数字,那么这应该只损失最小的精度。

    select put(&datevar,date9.) ,put(&currentvar,best32.) into :date1 ,:LEI
    ...
    values ("&date1"d, &LEI)
    

    但如果它是一个字符变量,那么你可能想要使用它。

    select put(&datevar,date9.), quote(&currentvar) into :date1,:LEI
    ...
    values ("&date1"d, &LEI)
    

    还要确保您用作 DATE 源的变量实际上具有 DATE 值而不是 DATETIME 值。如果 is 具有 DATETIME 值,那么您可以使用 DTDATE 格式生成正确格式的宏变量。或者使用 datepart() 函数仅提取日期值。

    请注意,将数据放入宏变量中是没有意义的,以便您以后可以将其放回数据中。所以你可以使用 PROC APPEND。

    %macro scoreprep(readtable,datevar,writetable);
    %local currentvar i ;
    %do i=1 %to %sysfunc(countw(&periods));
      %let currentvar=%scan(&periods,&i);
    proc sql;
      create table to_add as
        select &datevar as date 
             , &currentvar as forecast
        from &readtable
        where &currentvar is not null
        having &datevar=max(&datevar)
      ;
    quit;
    proc append data=to_add base=&writetable force ;
    run;
    
    %end;
    %mend;
    
    %scoreprep(rtchg1,date,Forecasts);
    

    或者甚至只是使用 SQL 代码插入查询结果。

    insert into &writetable (date,forecast)
      select &datevar, &currentvar
        from &readtable
        where &currentvar is not null
        having &datevar=max(&datevar)
    ;
    

    【讨论】:

    • 有趣!这种方式比我使用的方法更省时吗?
    • 忽略之前的(已删除的评论),效果很好!我看错表了哈哈。
    • 最大的区别在于准确性。如果将数据移动到宏变量中,则将其转换为文本。除了格式可能导致的混乱之外,它可能会丢失一些数字精度。 SAS 将数字存储为 IEEE 浮点值。
    • 添加了代码来回答您关于如何使数据 -> 宏变量 -> 数据往返工作的原始问题。
    • 就效率而言,您可能希望以某种方式格式化数据,以便单个 proc 可以在一次传递中生成您想要的所有数据行。如果您的数据格式正确,您很可能可以使用 PROC Summary 来执行此操作。
    【解决方案2】:

    尝试像这样更改这一行,看看是否有帮助:

        select &datevar format=date9., &currentvar into :date1, :LEI
    

    【讨论】:

    • 我试过了,得到了一个稍微不同的问题,我在尝试将 &date1 转换为代码末尾的日期变量之前看到的那种:> 错误 202-322:选项或参数是无法识别,将被忽略。
    • 此查询是否从表中返回多于一行?如果没有,那么这应该可以工作,否则您需要修改查询。
    • 它只返回一行,在尝试将 &datevar 插入表时似乎拒绝将其识别为日期变量。 &datevar 总是直接从日期列中提取,所以这对我来说很奇怪。
    猜你喜欢
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多