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

I've never expected the difficulty to perform a simple procuders with retain and first. statement.

My data look like this:

idjobnumfarm_everstartyearendyear
10041019551959
10042019591962
10043119621977
10081019511978
10082019781981
10111119541998
10121019651966
10122119661968
10123019681972
10124119721975
10125119752000
10141019591963
10142119631965
10143019651967
10144119671970
10145119701977
10146119781998
10147119981999

I need to calculate duration (endyear - startyear) when farm_ever = 1. When farm_ever = 1 continuously, I need duration across all jobnum. For example, when id=1014, farm_ever = 1 at jobnum 4, 5, 6, 7, the duration should be 1999-1967. I tried to use retain and first. statement :

 

proc sort data = jobhist ; by id jobnum farm_ever ; run ;

data jobhist ;
     set jobhist ;
     by id jobnum farm_ever ;
     retain start ;
     if first.farm_ever then start = startyear ;
run ;

 

But the results did not get retained because first.farm_ever is 1 for every entry. Then I tries proc sort without jobnum, but when farm_ever = 0, it went up to first, then the wrong year got retained. 

 

Could anyone please help me out? Is there any function to fix this, or is there any other statement to do this apart from retain? 

Thank you so much!

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

The sorted order is correct.  RETAIN is also correct.  Here's how  you might add to those pieces:

 

data want;

set jobhist;

by id farm_ever notsorted;

retain start;

if farm_ever=1 then do;

   if first.farm_ever then start = startyear;

   if last.farm_ever then duration = endyear - start;

end;

drop start;

run;

 

NOTSORTED permits the BY statement, even though the data are not in order by FARM_EVER.  You can see how the program utilizes first. and last. from that point.

View solution in original post

4 REPLIES 4
Astounding
PROC Star

The sorted order is correct.  RETAIN is also correct.  Here's how  you might add to those pieces:

 

data want;

set jobhist;

by id farm_ever notsorted;

retain start;

if farm_ever=1 then do;

   if first.farm_ever then start = startyear;

   if last.farm_ever then duration = endyear - start;

end;

drop start;

run;

 

NOTSORTED permits the BY statement, even though the data are not in order by FARM_EVER.  You can see how the program utilizes first. and last. from that point.

Tibby
Calcite | Level 5
Thank you so much for your help and for explaining notsorted. It worked just as the way I wanted.
ballardw
Super User

What about ID 1008 where farm_ever is never 1?

If the LAST value for Farm_ever going to be equal to 0 when it has been 1 in earlier jobnum values?

 

This may get close to the duration depending on responses to those questions.

data want ;
     set jobhist ;
     by id jobnum farm_ever ;
     retain start ;
     if first.id then start= -999;
     if farm_ever=1 and start=-999 then start=startyear;
     else if farm_ever=0 then start=-999;
     if last.id and start ne -999 then duration = endyear-start; 
run ;

BTW I recommend extreme caution with the

 

Data Jobhist;

   set Jobhist;

code. It is entirely too easy to end up with bad data if you recode any of your original variables. Multiple passes can recode multiple times.

Tibby
Calcite | Level 5

Thank you for your suggestion about data jobhist; set jobhist; I'll be more careful of using it. 

 

If for ID 1008 that farm_ever has never been 1, then no need to deal with it. The tricky part is to that LAST value for Farm_ever going to be equal to 0 when it has been 1 in earlier jobnum values.

 

The code you provided did pretty much most of the calculation but some tricky ones were missed. It was pretty close, though. Thank you for sharing your insight!

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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
  • 4 replies
  • 11133 views
  • 1 like
  • 3 in conversation