turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

Find a Community

- Home
- /
- SAS Programming
- /
- Base SAS Programming
- /
- DO help please

Topic Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-27-2011 12:47 PM

Good morning folks!

I'm stumped and need your help.

Basic premise - we are playing with various scenarios in our data, and one

of them is to adjust datasets based on critical values.

The logic flow is to take the original dataset (which is divided into

segment groupings), generate the statistic of interest by segment, and

compare it to the chosen critical values for that segment.

If the calculated statistic is smaller than the critical value for a

segment, send the data out to a 'completed' dataset (ITSDONE).

If the calculated statistic is larger than the critical value for a

segment, delete the largest value in the dataset, and repeat until the critical value test is

satisfied (NOTDONE).

Unfortunately, I can't seem to figure out how to stop the do loop when

the critical value test is satisfied (when NOTDONE is empty).

The particular combination we are looking at right now requires 751

iterations for all segments to meet the test criteria.

...until we change something (which we immediately will).

I need to be able to do this without 'knowing' anything but the critical value and statistic.

Thanks so much for your help!

Wendy T.

Dataset START already contains the critical value (K_CRIT), and is sorted

by descending values of the variable ANGLE_K by SEGMENT.

Dataset STACKER (to receive dataset ITSDONE) already exists, and contains

one line with null values.

DATA LOOP ; SET START ;

PROC MEANS NOPRINT N DATA=LOOP ;

BY SEGMENT ;

VAR ANGLE_K ;

OUTPUT OUT=ORIG1 (DROP= _TYPE_ _FREQ_) N=ORIGINAL_N ; RUN ;

RUN ;

%MACRO CUTTOPVALUE ;

%DO I=1 %TO 751 ;

PROC MEANS NOPRINT DATA=LOOP ;

BY SEGMENT ;

VAR ANGLE_K ;

OUTPUT OUT=MEDIANS (DROP=_TYPE_) MEDIAN=MEDIAN ;

RUN ;

PROC SQL NOPRINT ;

CREATE TABLE CHECKER

AS SELECT LOOP.*, MEDIANS.MEDIAN, MEDIANS._FREQ_

FROM LOOP, MEDIANS

WHERE LOOP.SEGMENT=MEDIANS.SEGMENT ;

QUIT ;

DATA ITSDONE NOTDONE (DROP=MEDIAN _FREQ_) ; SET CHECKER ;

IF MEDIAN LE K_CRIT THEN OUTPUT ITSDONE ;

ELSE OUTPUT NOTDONE ;

RUN ;

DATA STACKER ; SET ITSDONE STACKER ;

IF SEGMENT = '' THEN DELETE ;

PROC SORT ; BY SEGMENT ; RUN ;

DATA LOOP ; SET NOTDONE ;

IF _N_ = 1 THEN DELETE ;

RUN ;

%END ;

%MEND CUTTOPVALUE ;

%CUTTOPVALUE ;

DATA FINISHED ; MERGE STACKER ORIG1 ; BY SEGMENT ; RUN ;

I'm stumped and need your help.

Basic premise - we are playing with various scenarios in our data, and one

of them is to adjust datasets based on critical values.

The logic flow is to take the original dataset (which is divided into

segment groupings), generate the statistic of interest by segment, and

compare it to the chosen critical values for that segment.

If the calculated statistic is smaller than the critical value for a

segment, send the data out to a 'completed' dataset (ITSDONE).

If the calculated statistic is larger than the critical value for a

segment, delete the largest value in the dataset, and repeat until the critical value test is

satisfied (NOTDONE).

Unfortunately, I can't seem to figure out how to stop the do loop when

the critical value test is satisfied (when NOTDONE is empty).

The particular combination we are looking at right now requires 751

iterations for all segments to meet the test criteria.

...until we change something (which we immediately will).

I need to be able to do this without 'knowing' anything but the critical value and statistic.

Thanks so much for your help!

Wendy T.

Dataset START already contains the critical value (K_CRIT), and is sorted

by descending values of the variable ANGLE_K by SEGMENT.

Dataset STACKER (to receive dataset ITSDONE) already exists, and contains

one line with null values.

DATA LOOP ; SET START ;

PROC MEANS NOPRINT N DATA=LOOP ;

BY SEGMENT ;

VAR ANGLE_K ;

OUTPUT OUT=ORIG1 (DROP= _TYPE_ _FREQ_) N=ORIGINAL_N ; RUN ;

RUN ;

%MACRO CUTTOPVALUE ;

%DO I=1 %TO 751 ;

PROC MEANS NOPRINT DATA=LOOP ;

BY SEGMENT ;

VAR ANGLE_K ;

OUTPUT OUT=MEDIANS (DROP=_TYPE_) MEDIAN=MEDIAN ;

RUN ;

PROC SQL NOPRINT ;

CREATE TABLE CHECKER

AS SELECT LOOP.*, MEDIANS.MEDIAN, MEDIANS._FREQ_

FROM LOOP, MEDIANS

WHERE LOOP.SEGMENT=MEDIANS.SEGMENT ;

QUIT ;

DATA ITSDONE NOTDONE (DROP=MEDIAN _FREQ_) ; SET CHECKER ;

IF MEDIAN LE K_CRIT THEN OUTPUT ITSDONE ;

ELSE OUTPUT NOTDONE ;

RUN ;

DATA STACKER ; SET ITSDONE STACKER ;

IF SEGMENT = '' THEN DELETE ;

PROC SORT ; BY SEGMENT ; RUN ;

DATA LOOP ; SET NOTDONE ;

IF _N_ = 1 THEN DELETE ;

RUN ;

%END ;

%MEND CUTTOPVALUE ;

%CUTTOPVALUE ;

DATA FINISHED ; MERGE STACKER ORIG1 ; BY SEGMENT ; RUN ;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to WendyT

04-28-2011 02:19 AM

I'm not sure if I follow the logic in your program.

I'm guessing that in you last data step within the macro loop know if you need to iterate again or not.

If your don't need any more iterations, just call symput to a macro variable a certain value. This together with a %DO %WHILE or %UNTIL logic perhaps can do what you want?

/Linus

I'm guessing that in you last data step within the macro loop know if you need to iterate again or not.

If your don't need any more iterations, just call symput to a macro variable a certain value. This together with a %DO %WHILE or %UNTIL logic perhaps can do what you want?

/Linus

Data never sleeps

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to LinusH

05-03-2011 11:55 AM

I finally figured it out!

Sorry to not explain well. Yes, my object was to get the number of observations remaining in dataset LOOP to see if I needed to iterate again.

I was trying to use %symput to get the number of observations, but for some reason, I could not get it to work. (an example using call symput would be very welcome - I just now took a look at the documentation, and it's very unclear to me how to use it).

So I went another way and matched the DO UNTIL with PROC SQL to the dictionary table.

Thanks for your help!

Wendy T.

%MACROCUTTOPVALUE ;

%DO %UNTIL (&NUMBOBS = 0) ;

...as before ...

PROC SQL NOPRINT ;

SELECT NOBS INTO :NUMBOBS FROM SASHELP.VTABLE

WHERE LIBNAME='WORK' AND MEMNAME='LOOP' ;

QUIT;

%END ;

%MEND CUTTOPVAL ;

Sorry to not explain well. Yes, my object was to get the number of observations remaining in dataset LOOP to see if I needed to iterate again.

I was trying to use %symput to get the number of observations, but for some reason, I could not get it to work. (an example using call symput would be very welcome - I just now took a look at the documentation, and it's very unclear to me how to use it).

So I went another way and matched the DO UNTIL with PROC SQL to the dictionary table.

Thanks for your help!

Wendy T.

%MACROCUTTOPVALUE ;

%DO %UNTIL (&NUMBOBS = 0) ;

...as before ...

PROC SQL NOPRINT ;

SELECT NOBS INTO :NUMBOBS FROM SASHELP.VTABLE

WHERE LIBNAME='WORK' AND MEMNAME='LOOP' ;

QUIT;

%END ;

%MEND CUTTOPVAL ;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to WendyT

05-03-2011 06:44 PM

Hi:

For some general macro overviews -- on overall macro processing and SYMPUT (among other topics), perhaps these papers will prove easier to go through:

http://www2.sas.com/proceedings/sugi29/052-29.pdf

http://support.sas.com/resources/papers/proceedings11/119-2011.pdf

http://www.lexjansen.com/wuss/2006/CodersCorner/COD-Gustafson.pdf

http://www.nesug.org/proceedings/nesug98/code/p088.pdf

cynthia

For some general macro overviews -- on overall macro processing and SYMPUT (among other topics), perhaps these papers will prove easier to go through:

http://www2.sas.com/proceedings/sugi29/052-29.pdf

http://support.sas.com/resources/papers/proceedings11/119-2011.pdf

http://www.lexjansen.com/wuss/2006/CodersCorner/COD-Gustafson.pdf

http://www.nesug.org/proceedings/nesug98/code/p088.pdf

cynthia

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to WendyT

05-05-2011 07:53 AM

Instead of adding a separate PROC SQL step, you could just modify the last data step as follows. Code additions are documented in comments:

DATA LOOP ;

/* Detect how many observations are in NOTDONE with nobs= */

SET NOTDONE nobs=NumObs;

/* Write the remining number of iterations to the NUMBOBS macro variable */

call symputx("NUMBOBS",NumObs-1);

IF _N_ = 1 THEN DELETE ;

RUN ;

DATA LOOP ;

/* Detect how many observations are in NOTDONE with nobs= */

SET NOTDONE nobs=NumObs;

/* Write the remining number of iterations to the NUMBOBS macro variable */

call symputx("NUMBOBS",NumObs-1);

IF _N_ = 1 THEN DELETE ;

RUN ;

- Mark as New
- Bookmark
- Subscribe
- RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

Posted in reply to WendyT

04-28-2011 02:44 AM

It would be helpful if you can post some data ,and explain what output you want after every iteration.

Ksharp

Ksharp