【问题标题】:SAS - creating indicator variablesSAS - 创建指标变量
【发布时间】:2018-08-24 08:21:23
【问题描述】:

我正在使用 SAS,我想创建一个指标变量。

我拥有的数据是这样的(DATA I HAVE):

我想将其更改为(我想要的数据):

我有一个固定数量的总时间要使用,并且 starttime 具有重复的时间值(在此示例中,c1 和 c2 都在时间 3 开始)。虽然我使用的示例很小,有 5 个名称和 12 个时间值,但实际数据非常大(大约 40,000 个名称和 100,000 个时间值 - 所以我想要的结果是一个 100,000x40,000 的矩阵。)

有人可以提供有关如何处理此问题的任何提示/解决方案吗?

【问题讨论】:

标签: sas


【解决方案1】:

40k 变量很多。看看这个规模有多好会很有趣。你如何确定停止时间?

data have;
    input starttime name :$32.;
    retain one 1;
    cards;
1 varx
3 c1
3 c2
5 c3x
10 c4
11 c5
;;;;
   run;
proc print;
   run;
proc transpose data=have out=have2(drop=_name_ rename=(starttime=time));
   by starttime;
   id name;
   var one;
   run;
data time;
   if 0 then set have2(drop=time);
   array _n[*] _all_;
   retain _n 0;
   do time=.,1 to 12;
      output;
      call missing(of _n[*]);
      end;
   run;
data want0 / view=want0;
   merge time have2;
   by time;
   retain dummy '1';
   run;
data want;
   length time 8;
   update want0(obs=0) want0;
   by dummy;
   if not missing(time);
   output;
   drop dummy;
   run;
proc print;
   run;

【讨论】:

    【解决方案2】:

    这会奏效。可能有一种更简单的解决方案可以在一个数据步骤中完成所有操作。我的数据步骤创建了一个必须折叠的交错结果,我通过对排序/均值求和来做到这一点。

    data have;
        input starttime name $;
        datalines;
    3 c1
    3 c2
    5 c3
    10 c4
    11 c5
    ;
    run;
    
    data want(drop=starttime name);
        set have;
        array cols (*) c1-c5;
        do time=1 to 100;
            if starttime < time then cols(_N_)=1;
            else cols(_N_)=0;
            output;
        end;
    run;
    
    proc sort data=want;
        by time;
    proc means data=want noprint;
        by time;
        var _numeric_;
        output out=want2(drop=_type_ _freq_) sum=;
    run;
    

    我不建议你这样做。您没有提供足够的信息来让我们知道您为什么需要这种大小的矩阵。您可能在运行它时遇到处理问题。

    do time=1 to 100 行中,您可以将其更改为 100000 或任何长度。

    【讨论】:

      【解决方案3】:

      我认为下面的代码会起作用:

      %macro answer_macro(data_in, data_out);
      
      /* Deduplication of initial dataset just to assure that every variable has a unique starting time*/
      proc sort data=&data_in. out=data_have_nodup; by name starttime; run;
      proc sort data=data_have_nodup nodupkey; by name; run;
      
      /*Getting min and max starttime values - here I am assuming that there is only integer values form starttime*/
      proc sql noprint;
          select min(starttime)
                  ,max(starttime) 
          into :min_starttime /*not used. Use this (and change the loop on the next dataset) to start the time variable from the value where the first variable starts*/
              ,:max_starttime
          from data_have_nodup
      ;quit;
      
      /*Getting all pairs of name/starttime*/
      proc sql noprint;
          select name
                  ,starttime
          into :name1 - :name1000000
              ,:time1 - :time1000000
          from data_have_nodup
      ;quit;
      
      /*Getting total number of variables*/
      proc sql noprint;
          select count(*) into :nvars
          from data_have_nodup
      ;quit;
      
      /* Creating dataset with possible start values */
      /*I'm not sure this step could be done with a single datastep, but I don't have SAS 
      on my PC to make tests, so I used the method below*/
      
      data &data_out.;
          do i = 1 to &max_starttime. + 1;
              time = i; output;
          end;
          drop i;
      run;
      
      data &data_out.;
          set &data_out.;
          %do i = 1 %to &nvars.;
              if time >= &&time&i then &&name&i = 1;
              else &&name&i = 0;
          %end;
      run;
      
      %mend answer_macro;
      

      很遗憾,我的机器上现在没有 SAS,所以我无法确认代码是否有效。但即使没有,你也可以使用其中的逻辑。

      【讨论】:

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