【问题标题】:Converting wide data to narrow in SAS using substr使用 substr 在 SAS 中将宽数据转换为窄数据
【发布时间】:2017-03-07 17:13:49
【问题描述】:

我在 SAS 中有一个宽数据集,一年中的每个月都有单独的列,结构为:“Aug__2015”到“Aug__2016”。有些月份有两个下划线,有些月份有一个。基本上,我需要使用 substr 创建一个新的 Month 变量和一个 Year 变量,并有一个看起来像附加输出的输出。通常,我只会使用 proc transpose,但我们必须使用几个代码块和 if-then 语句来代替。这是我在 2015 年 8 月尝试过的代码的截断版本。我遇到了很多错误...

data work.jobs;
set DownL.Tabled1x2016;
    Industry=propcase(Industry);
    if substr(Aug__2015, length(Aug__2015),4)='2015' and not missing(Aug__2015) then do;
    Year=substr(Aug__2015, length(Aug__2015), 4);
    Month=substr(Aug__2015, 1, 3);
end;
run;

不知何故,对于一年中的每个月,我都需要单独的 if-then 块,从而产生月份和年份的字符值。提前感谢您的指导。

【问题讨论】:

    标签: sas


    【解决方案1】:

    使用数组和 vname() 函数。

    data work.jobs;
    set DownL.Tabled1x2016;
        format tmp $32.;
        array mths[*] Aug__2015 -- Aug__2016;
        Industry=propcase(Industry);
        do i=1 to dim(mths);
            tmp = compress(vname(mths[i]),'_');
            Month = substr(tmp,1,3);
            Year = substr(tmp,4);
            jobs = mths[i];
            output;
        end;
        drop tmp i Aug__2015 -- Aug__2016;
    run;
    

    array mths[*] Aug__2015 -- Aug__2016; 这将创建一个变量数组,该数组以Aug__2015 开头并以Aug_2016 结尾。或者,您可以单独列出所有变量。

    * 是一个通配符,允许您不定义数组大小 - 让 SAS 为您完成。

    SAS Data Step 数组只是指向表中变量的指针的逻辑构造。

    【讨论】:

    • 你能解释一下数组语句(特别是带有mths[*]的部分)吗?
    • 感谢您的解释。然后,一旦我选择了 3 个字母的月份指标,我可以使用 If-then 语句将它们重命名为完整的月份名称吗? (例如 9 月 -> 9 月)
    【解决方案2】:

    编辑:根据提供的示例数据更新。

    %let months=Aug__2015*Sept__2015*Oct__2015*Nov__2015*Dec__2015*
      Jan__2016*Feb__2016*Mar__2016*Apr__2016*May_2016*
      June_2016*July_2016*Aug__2016;
    %let fmonths=August*September*October*November*December*
      January*February*March*April*May*June*July*August;
    %let fyears=2015*2015*2015*2015*2015*
      2016*2016*2016*2016*2016*2016*2016*2016;
    
    DATA dset2;
      SET dset1;
      FORMAT month $9.;
      %do i=1 %to 13;
        %let var=%scan(&months., &i., *);
        %let fmonth=%scan(&fmonths., &i., *);
        %let fyear=%scan(&fyears., &i., *);
        IF NOT MISSING(&var.) THEN DO;
          jobs=&var.;
          month="&fmonth.";
          year=&fyear.;
          OUTPUT;
        END;
      %end;
    RUN;
    

    @DomPazz 的答案更简洁。这个更灵活。

    【讨论】:

    • 我刚刚添加了前五个观察结果。
    • let 和 do 前面的 % 是做什么用的?另外,变量前面的 & 和字母 i?
    • 这是 SAS 宏代码。 %let 定义了一个可调用的宏变量。 & 调用变量。将宏代码视为一种以更简单的方式编写复杂和/或重复代码的方法。我强烈建议学习基础知识以改进 SAS 编码。
    • 编码世界就像一片深不可测的海洋。感谢您的解释!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2015-06-14
    相关资源
    最近更新 更多