0

假设我有以下数据库:

Min Rank Qty
2   1    100
2   2    90
2   3    80 
2   4    70
5   1    110
5   2    100
5   3    90
5   4    80
5   5    70
7   1    120
7   2    110
7   3    100
7   4    90

我需要让数据库具有连续几分钟的值,如下所示:

Min Rank Qty
2   1    100
2   2    90
2   3    80 
2   4    70
3   1    100
3   2    90
3   3    80 
3   4    70
4   1    100
4   2    90
4   3    80 
4   4    70
5   1    110
5   2    100
5   3    90
5   4    80
5   5    70
6   1    110
6   2    100
6   3    90
6   4    80
6   5    70
7   1    120
7   2    110
7   3    100
7   4    90

我怎样才能在 SAS 中做到这一点?我只需要复制前一分钟。每分钟的观察次数各不相同……可以是 4 次或 5 次或更多。

4

2 回答 2

0

不难想象代码会这样做,问题是它很快就会开始看起来很乱。

如果您的数据集不是太大,您可以考虑以下一种方法:

/* We find all gaps. the output dataset is a mapping: the data of which minute (reference_minute) do we need to create each minute of data*/
data  MINUTE_MAPPING (keep=current_minute reference_minute);
    set YOUR_DATA;
    by min;
    retain last_minute 2; *set to the first minute you have;

    if _N_ NE 1 and first.min then do;
        /* Find gaps, map them to the last minute of data we have*/
        if last_minute+1 < min then do;
            do current_minute=last_minute+1 to min-1;
                reference_minute=last_minute;
                output;
            end;
        end;

        /* For the available data, we map the minute to itself*/
        reference_minute=min;
        current_minute=min;
        output;

        *update;
        last_minute=min;
    end;
run;

/* Now we apply our mapping to the data */
*you must use proc sql because it is a many-to-many join, data step merge would give a different outcome;
proc sql;
    create table RESULT as
    select YD.current_minute as min, YD.rank, YD.qty
    MINUTE_MAPPING as MM
    join YOUR_DATA as YD
    on (MM.reference_minute=YD.min)
    ;
quit;

更高效的方法将涉及数组的诡计。但我发现这种方法更有吸引力(免责声明:起初认为),之后为其他人更快地掌握(再次免责声明:恕我直言)。


为了更好地衡量,数组方法:

data  RESULT (keep=min rank qty);
    set YOUR_DATA;
    by min;
    retain last_minute; *assume that first record really is first minute;
    array last_data{5} _TEMPORARY_;

    if _N_ NE 1 and first.min and last_minute+1 < min then do; *gap found;
        do current_min=last_minute+1 to min-1;
            *store data of current record;
            curr_min=min;
            curr_rank=rank;
            curr_qty=qty;

            *produce records from array with last available data;
            do iter=1 to 5;
                min = current_minute;
                rank = iter;
                qty = last_data{iter};
                if qty NE . then output; *to prevent output of 5th element where there are only 4;
            end;

            *put back values of actual current record before proceeding;
            min=curr_min;
            rank=curr_rank;
            qty=curr_qty;
        end;

        *update;
        last_minute=min;
    end;

    *insert data for use on later missing minutes;
    last_data{rank}=qty;
    if last.min and rank<5 then last_data{5}=.;

    output; *output actual current data point;
run;

希望能帮助到你。请注意,目前无法访问我所在的 SAS 客户端。所以未经测试的代码,可能包含几个错字。

于 2013-10-03T18:54:16.737 回答
0

除非您的观察数量荒谬,否则我认为转置会使这变得容易。

我目前无法访问 sas,所以请耐心等待(如果你不能让它工作,我明天可以测试它)。

proc transpose data=data out=data_wide prefix=obs_;
  by minute;
  id rank;
  var qty;
run;

*sort backwards so you can use lag() to fill in the next minute;
proc sort data=data_wide;
  by descending minute;
run;

data data_wide; set data_wide;
  nextminute = lag(minute);
run;

proc sort data=data_wide;
  by minute;
run;

*output until you get to the next minute;
data data_wide; set data_wide;
  *ensure that the last observation is output;
  if nextminute = . then output;
  do until (minute ge nextminute);
    output;
    minute+1;
  end;
run;

*then you probably want to reverse the transpose;
proc transpose data=data_wide(drop=nextminute)
               out=data_narrow(rename=(col1=qty));
  by minute;
  var _numeric_;
run;

*clean up the observation number;
data data_narrow(drop=_NAME_); set data_narrow;
  rank = substr(_NAME_,5)*1;
run;

同样,我现在无法对此进行测试,但它应该可以工作。

其他人可能有一个聪明的解决方案,所以你不必反向排序/滞后/前向排序。我觉得我之前已经处理过这个问题,但现在对我来说明显的解决方案是让它在你之前所做的任何排序中向后排序(你可以用降序进行转置没问题),以节省额外的排序。

于 2013-10-04T01:10:42.277 回答