BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
chithra
Quartz | Level 8

Dear All,

 

I am having a data set like below :

 

idscnyearvalue
891168100000
8911690
891169111111
8911710
8911710
891172100003
891179100004
8911800
892168100006
8921690
892172100008

 

The columns id,scn and year is sorted in ascending order, i mean all are group by.

year column should be consecutive numbers, but here some year are missing, I need to add consecutive numbers in between with value as 0.

i need to do this in data step becuase it is very huge data, multiple steps will cause performance issue.

 

The output should lokks like :

idscnyearvalue
891168100000
8911690
891169111111
8911700
8911710
8911710
891172100003
8911730
8911740
8911750
8911760
8911770
8911780
891179100004
8911800
892168100006
8921690
8921700
8921710
892172100008

 

Thanks in Advance,

Chithra

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

In that case, you're better of using @ErikLund_Jensen 's method of lookahead, as it already uses by-processing:

%let start=167;

data want (drop=_year _value nextyear); 
  set have;
  by id scn;
  nextrec = _N_ + 1;
  if first.scn then do;
    _year = year;
    _value = value;
    do year = &start to year - 1;
      value = 0;
      output;
    end;
    value = _value;
    year = _year;
  end;
  output;
  if not last.scn then do;
    set have (keep=year rename=(year=nextyear)) point=nextrec;
    do year = year + 1 to nextyear - 1;
      value = 0;
      output;
    end;
  end;
run;

View solution in original post

6 REPLIES 6
Kurt_Bremser
Super User

Create a "look-ahead":

data have;
infile datalines dlm='09'x dsd;
input id $ scn year value;
datalines;
89	1	168	100000
89	1	169	0
89	1	169	111111
89	1	171	0
89	1	171	0
89	1	172	100003
89	1	179	100004
89	1	180	0
89	2	168	100006
89	2	169	0
89	2	172	100008
;
run;

data want;
merge
  have
  have (
    firstobs=2
    keep=id scn year
    rename=(
      id=n_id
      scn=n_scn
      year=n_year
    )
  )
;
output;
if n_id = id and n_scn = scn
then do year = year + 1 to n_year - 1;
  value = 0;
  output;
end;
drop n_:;
run;

proc print data=want noobs;
run;

Result:

id    scn    year     value

89     1      168    100000
89     1      169         0
89     1      169    111111
89     1      170         0
89     1      171         0
89     1      171         0
89     1      172    100003
89     1      173         0
89     1      174         0
89     1      175         0
89     1      176         0
89     1      177         0
89     1      178         0
89     1      179    100004
89     1      180         0
89     2      168    100006
89     2      169         0
89     2      170         0
89     2      171         0
89     2      172    100008

Note how I presented your example data in a data step with datalines, so it is easy for others to recreate the dataset. Please do so in the future; help us to help you.

chithra
Quartz | Level 8

Many thanks.

This is working

ErikLund_Jensen
Rhodochrosite | Level 12

Hi @chithra 

 

Here is a slightly different way of doing just the same as Kurtbremser's code. It uses the point= option instead of firstobs=2. It is in no way better, I just post it because I want to promote use of the point= option, because it is so useful for look-ahead and -back, also in more complicated cases.

 

data want (drop= lastyear nextyear i); 
	set have; by id scn;
	nextrec = _N_ + 1;
	lastyear = year;
	output;
	if not last.scn then do;
		set have (keep=year rename=(year=nextyear)) point=nextrec;
		do i = lastyear + 1 to nextyear - 1;
			year = i;
			value = 0;
			output;
		end;
	end;
run;

 

 

chithra
Quartz | Level 8

just one modification to this.

The firt observation can be changed, it is not constant. that is if 168 is not the first observation, the first observation is missed, that was actually 167. 

that number can be found out and stored in a macro or in some other way, that is possible.(may be that is the min of the whole table etc..)

THen how can we modify this?

Kurt_Bremser
Super User

In that case, you're better of using @ErikLund_Jensen 's method of lookahead, as it already uses by-processing:

%let start=167;

data want (drop=_year _value nextyear); 
  set have;
  by id scn;
  nextrec = _N_ + 1;
  if first.scn then do;
    _year = year;
    _value = value;
    do year = &start to year - 1;
      value = 0;
      output;
    end;
    value = _value;
    year = _year;
  end;
  output;
  if not last.scn then do;
    set have (keep=year rename=(year=nextyear)) point=nextrec;
    do year = year + 1 to nextyear - 1;
      value = 0;
      output;
    end;
  end;
run;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 1736 views
  • 1 like
  • 3 in conversation