Thursday, January 20, 2011

How to assign the value of prevoius observation to current observations

/*  This question comes from mitbbs, the question is:
**************************************************************
Data is something like shown below

id     eventDay    
001     3
002     2
003     4
003     5
004     3
004     4
004     5
004     11
004     20

Want to get two more column "start" "stop"

id     eventDay    start    stop 
001     3           0        3
002     2           0        2
003     4           0        4
003     5           4        5
004     3           0        3
004     4           3        4
004     5           4        5
004    11           5        11
004    20           11       20

How can I get "start" value from the "stop" value of the previous
observation of the same ID?
******************************************************************
*/

/********************** Original data input ********************/
data song;
input id     eventDay;
cards;
001     3
002     2
003     4
003     5
004     3
004     4
004     5
004     11
004     20
;
run;

proc sort data=song;
  by id;
run;


/***************   Method one: Using LAG function   *************/;
data new;
  set  song;
  by   id;
       stop=eventday;
          start=lag(eventday);
  if   first.id then start=0;
run;

proc print data=&syslast;
  var id eventday start stop;
run;
 
/***************   Method two: Using Retain function   *************/;

proc sort data=ss;
  by id;
run;

data new;
  set ss;
  by id;
  retain stop;
  if first.id then start=0;
  else start=stop;   
  stop=eventday;  /* Pay attention to variables' order here */
run;

proc print data=&syslast;
  var id eventday start stop;
run;

1 comment:

  1. data one;
    i + 1;
    input id $ eventDay;
    datalines;
    001 3
    002 2
    003 4
    003 5
    004 3
    004 4
    004 5
    004 11
    004 20
    ;
    run;

    proc sql;
    create table
    two (drop = i) as
    select
    a.*,
    max(0, b.eventday) as start,
    a.eventday as stop
    from
    one as a left join one as b
    on a.id = b.id and a.i - 1 = b.i;
    quit;

    ReplyDelete