LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (May 2010, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Tue, 11 May 2010 10:26:37 -0400
Reply-To:     Chang Chung <chang_y_chung@HOTMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Chang Chung <chang_y_chung@HOTMAIL.COM>
Subject:      Re: Alternative for "goto" in do loop
Comments: To: Sid N <nsid31@GMAIL.COM>

On Mon, 10 May 2010 23:12:33 -0400, Sid N <nsid31@GMAIL.COM> wrote:

>Hi, > >I am trying to understand the "goto" sequences in the second data step >below: > >data range1; >informat start end date9.; >format start end date9.; >input start end; >start_m = month(start); >end_m = month(end); >start_y = year(start); >end_y = year(end); >cards; >01JAN1975 01JAN1977 >01AUG1979 01JUL1980 >01MAR2008 01JAN2010 >01DEC2000 01SEP2002 >01FEB2010 01NOV2011 >; >run; > >data range2; >set range1; >do y = start_y to end_y by 1; >if y < 1980 then goto skip3; >if y > 2009 then goto skip2; > do m = 1 to 12 by 1; > if (start_m > m and y = start_y) then goto skip1; > if (y = end_y and end_m < m) then goto skip2; > output; > skip1:; > end; >skip3:; >end; >skip2:; >run; > > >Can someone please help me understand the "goto" sequences in the above "do >loop"? I have heard that using "goto" sequences may not be an efficient way >to code in SAS. Please suggest an alternative to output what the above code >is accomplishing using different programming logic.

Hi, sid: The data step range2 must have written by someone who does not know SAS at all, not to mention the date/time programming. It seems that the purpose of the step is to output as many observations as the number of months between the given interval, inclusively at both ends. It also seems that the interval is to be truncated if it goes outside of another range, jan1980-dec2009. If this is the case, then one can code it SAS way like below. I did not understand what the variable m in the range2 is for, so I changed it to something more useful in my data step. Ran on 9.2(TS1M0) on W32_VSPRO. HTH. Cheers, Chang

/* test data */ data range1; informat start end date9.; format start end date9.; input start end; start_m = month(start); end_m = month(end); start_y = year(start); end_y = year(end); cards; 01JAN1975 01JAN1977 01AUG1979 01JUL1980 01MAR2008 01JAN2010 01DEC2000 01SEP2002 01FEB2010 01NOV2011 ; run;

/* this will never pass any SAS code review session! */ data range2; set range1; do y = start_y to end_y by 1; if y < 1980 then goto skip3; if y > 2009 then goto skip2; do m = 1 to 12 by 1; if (start_m > m and y = start_y) then goto skip1; if (y = end_y and end_m < m) then goto skip2; output; skip1:; end; skip3:; end; skip2:; run;

/* a rewrite of data step above. a SAS way */ data range3; set range1(keep= start end); begin_month = max(start, '01jan1980'd); end_month = min(end, '01dec2009'd); m = begin_month; do while (m <= end_month); output; m = intnx('month', m, 1); end; keep start end m; format m yymmn7.; run;

/* check */ proc compare base=range2(keep=start end) compare=range3; run; /* on lst NOTE: No unequal values were found. All values compared are exactly equal. */

proc print data=range3(obs=30); run; /* on lst Obs start end m

1 01AUG1979 01JUL1980 198001 2 01AUG1979 01JUL1980 198002 3 01AUG1979 01JUL1980 198003 4 01AUG1979 01JUL1980 198004 5 01AUG1979 01JUL1980 198005 6 01AUG1979 01JUL1980 198006 7 01AUG1979 01JUL1980 198007 8 01MAR2008 01JAN2010 200803 9 01MAR2008 01JAN2010 200804 10 01MAR2008 01JAN2010 200805 11 01MAR2008 01JAN2010 200806 12 01MAR2008 01JAN2010 200807 13 01MAR2008 01JAN2010 200808 14 01MAR2008 01JAN2010 200809 15 01MAR2008 01JAN2010 200810 16 01MAR2008 01JAN2010 200811 17 01MAR2008 01JAN2010 200812 18 01MAR2008 01JAN2010 200901 19 01MAR2008 01JAN2010 200902 20 01MAR2008 01JAN2010 200903 21 01MAR2008 01JAN2010 200904 22 01MAR2008 01JAN2010 200905 23 01MAR2008 01JAN2010 200906 24 01MAR2008 01JAN2010 200907 25 01MAR2008 01JAN2010 200908 26 01MAR2008 01JAN2010 200909 27 01MAR2008 01JAN2010 200910 28 01MAR2008 01JAN2010 200911 29 01MAR2008 01JAN2010 200912 30 01DEC2000 01SEP2002 200012 */


Back to: Top of message | Previous page | Main SAS-L page