BookmarkSubscribeRSS Feed
WendyT
Pyrite | Level 9
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 ;
5 REPLIES 5
LinusH
Tourmaline | Level 20
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
Data never sleeps
WendyT
Pyrite | Level 9
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 ;
Cynthia_sas
SAS Super FREQ
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
SASJedi
SAS Super FREQ
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 ;
Check out my Jedi SAS Tricks for SAS Users
Ksharp
Super User
It would be helpful if you can post some data ,and explain what output you want after every iteration.


Ksharp

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
  • 5 replies
  • 876 views
  • 0 likes
  • 5 in conversation