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
- /
- General Programming
- /
- Does anyone has more experience with Proc Surveyse...

Topic Options

- Subscribe to 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
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content

12-17-2013 02:35 AM

I want to randomly sample each one of my ten fields until it achieve the precision of 0.10. I mean, I want to sample with replacement each field and save the mean and variance of insects. Precision is calculated dividing the standard error of mean by mean (SEM/m). For instance, when my sample size is 20, my precision is 0.40. Increasing sample size will increase precision (i.e., 300 samples will give me the desired precision of 0.10).

I attached my data set. I believe the problem is in the loop.

/*DATA Tibraca;

INPUT Field Adult ;*/

%LET J=100.10;

%LET K=100.20001; /*Starting the process with a valid statement, K>100.20*/

%LET I=1; /*This is my initial sample size*/

%MACRO Sampling;

%DO %UNTIL (K>100.20); /*When I have precision=0.10, K will not be greater than 100.20, 100.10 (J) + 0.10 (Prec) = 100.20. It will kill the process*/

/*If I have a small sample size (i), Prec will be greter than 0.10. Then, process will keep going because K is not less than 100.20*/

PROC SORT DATA=TIBRACA; BY Field; RUN;

PROC SURVEYSELECT DATA=TIBRACA NOPRINT

OUT = SimpleSample

METHOD = SRS

SAMPSIZE = &I; /*Sample size*/

STRATA Field; /*I have 10 fields that should be considered separately*/

RUN;

DATA MERGING;

SET SimpleSample;

RUN;

PROC MEANS DATA=MERGING MEAN STDERR N NOPRINT; /*Calculating mean and SEM, later Precision=SEM/m*/

BY Field;

VAR Adult;

OUTPUT OUT=STATS; RUN;

DATA STATS2;

SET STATS;

IF _STAT_ ="MEAN" THEN AVG=Adult; /*Dummy variables*/

IF _STAT_ ="STD" THEN SEM=Adult;

RUN;

/*Putting Mean and SEM in the same raw because I need to calculate SEM/mean*/

PROC MEANS DATA=STATS2 NOPRINT; CLASS Field; VAR AVG; OUTPUT OUT=STATS3; RUN;

PROC MEANS DATA=STATS2 NOPRINT; CLASS Field; VAR SEM; OUTPUT OUT=STATS4; RUN;

DATA STATS5;

MERGE STATS3 STATS4;

IF _STAT_ ^="MEAN" THEN DELETE;

IF Field ="." THEN DELETE;

PREC=SEM/AVG; /*Calculating precision for each run with &I sample size*/

RUN;

%put I=&I+1; /***Is here the problem?***/

%put K=&J+PREC; /*Testing if I the sample size is already enough to have PREC=0.10.*/

%END;

%MEND Sampling;

%Sampling

RUN;

PROC PRINT DATA=STATS5; RUN; Title "Stopped with &I samples"; RUN;

Accepted Solutions

Solution

12-17-2013
10:38 PM

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

12-17-2013 10:38 PM

Dear peers,

**I appreciated so much your help.**

After several consecutive hours, I have figured out this code.

My process will sample with replacement the field and stops when achieve a precision of 0.10.

I am pasting this code here. I hope that it saves time of someone else...

It may be dirty yet. It is my first macro code in SAS.

**%LET d=100.20001;**

**%LET i=1; **

**%LET PREC=0; RUN;**

**%MACRO Sampling;**

**%DO %WHILE (&d>100.10 or &d<10); **

** PROC SURVEYSELECT DATA=ONLYFIELD NOPRINT **

** OUT = SimpleSample**

** METHOD = URS OUTHITS /*Simple Random, With replacement*/**

** N = &i; /*Sample size*/**

** RUN; **

** PROC MEANS DATA=SimpleSample MEAN STD N NOPRINT; **

** VAR Adult;**

** OUTPUT OUT=STATS MEAN=AVG STD=STDEV N=NUM; RUN; **

** DATA STATS2;**

** SET STATS;**

** SNUM=SQRT(NUM);**

** PREC=(STDEV/(AVG*SNUM)); **

** d=(PREC+100);**

** call symput('AVG',AVG); **

** call symput('d',d); **

** call symput('PREC',PREC); **

** RUN; **

** %LET i=%eval(&i+1);**

** Title "Sample size is &i units, prec is &PREC, d is &d, avg is &avg."; RUN;**

** PROC PRINT DATA=STATS2; RUN;**

**%END;**

**%MEND Sampling;**

**%Sampling**

**RUN;**

All Replies

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

12-17-2013 11:17 AM

You may have more than one mistake, but for starters... This should be &K not K

%DO %UNTIL (K>100.20);

And I believe that

%put I=&I+1; /***Is here the problem?***/

%put K=&J+PREC; /*Testing if I the sample size is already enough to have PREC=0.10.*/

Should be %LET rather than %PUT, as put displays variable and LET creates variables.

You may also want to add the %eval function to those,

%let I=%eval(&I+1); /***Is here the problem?***/

%let K=%eval(&J+PREC); /*Testing if I the sample size is already enough to have PREC=0.10.*/

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

12-17-2013 02:18 PM

Since the example code shows J and K with decimal components you'll %sysevalf to do floating point addition.

It doesn't look like PREC is a variable in a data set so the &J + PREC is likely not to work as PREC will be treated as a string and fail.

You probably need to create anothe macro variable: %Let Prec= 0.10;

and use &J + &Prec.

However, if you are determining sample sizes you might want to look at proc power to determine sample size since you should have mean and stddev of your varibles as starting point, specify the precision you need.

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

12-17-2013 03:04 PM

I'm going to make my question easier. I believe that I did not understand how to do the loop in SAS. See this simple code below. It runs the first loop, but doesn't go the the next I+1 loop. Thanks.

Header 1 | Header 2 |
---|---|

%let I=5; %macro Do_Tests; DATA TWO; %do %while (&I>0); %LET C=%eval(&I+50); Ivar=&I; Cvar=&C; RUN; PROC PRINT DATA=TWO; RUN; %LET I=%eval(&I-1); %end; %mend Do_Tests; %Do_Tests |
Ivar Cvar 5 55 4 54 3 53 2 52 1 51 |

Header 1 | Header 2 |
---|---|

%let I=0; %macro Do_Tests; DATA TWO; %do %until (&I<5); %LET C=%eval(&I+50); Ivar=&I; Cvar=&C; RUN; PROC PRINT DATA=TWO; RUN; %LET I=%eval(&I+1); %end; %mend Do_Tests; %Do_Tests |
Ivar Cvar 0 50 1 51 2 52 3 53 4 54 ? |

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

12-17-2013 03:26 PM

Your initial code is different than your sample code in one key respects. If you're looking to loop within a datastep you don't need to use macro logic. If you're looping multiple procedures then you'll need macro logic.

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

12-17-2013 04:13 PM

You are confused about when macro code runs relative to when the generated SAS code that it creates run.

Your UNTIL condition seems reversed. If you start I at 0 and increment it by only 1 then it will always be less than 5.

If you want one pass of a datastep to output multiple observations you need to include an OUTPUT statement.

Your problem does not require macro logic.

DATA TWO;

do ivar = 5 to 1 by -1 ;

Cvar=ivar+50;

OUTPUT;

end;

run;

Solution

12-17-2013
10:38 PM

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

12-17-2013 10:38 PM

Dear peers,

**I appreciated so much your help.**

After several consecutive hours, I have figured out this code.

My process will sample with replacement the field and stops when achieve a precision of 0.10.

I am pasting this code here. I hope that it saves time of someone else...

It may be dirty yet. It is my first macro code in SAS.

**%LET d=100.20001;**

**%LET i=1; **

**%LET PREC=0; RUN;**

**%MACRO Sampling;**

**%DO %WHILE (&d>100.10 or &d<10); **

** PROC SURVEYSELECT DATA=ONLYFIELD NOPRINT **

** OUT = SimpleSample**

** METHOD = URS OUTHITS /*Simple Random, With replacement*/**

** N = &i; /*Sample size*/**

** RUN; **

** PROC MEANS DATA=SimpleSample MEAN STD N NOPRINT; **

** VAR Adult;**

** OUTPUT OUT=STATS MEAN=AVG STD=STDEV N=NUM; RUN; **

** DATA STATS2;**

** SET STATS;**

** SNUM=SQRT(NUM);**

** PREC=(STDEV/(AVG*SNUM)); **

** d=(PREC+100);**

** call symput('AVG',AVG); **

** call symput('d',d); **

** call symput('PREC',PREC); **

** RUN; **

** %LET i=%eval(&i+1);**

** Title "Sample size is &i units, prec is &PREC, d is &d, avg is &avg."; RUN;**

** PROC PRINT DATA=STATS2; RUN;**

**%END;**

**%MEND Sampling;**

**%Sampling**

**RUN;**