SAS: Do while loop not iterating

可紊 提交于 2019-12-11 08:24:02

问题


I have a saved csv_files SAS Dataset with the following entries:

name path
aapl F:\Data\aapl.csv
msft F:\Data\msft.csv
ibm F:\Data\ibm.csv
goog F:\Data\goog.csv

I then use this SAS dataset to locate the csv files and import them into SAS using the following Macro which has a while loop:

options symbolgen mlogic nomprint;  
/*Leave options on as SAS will issue a message when Do While Loop is false*/

%let dsname = csv_files;                               
%let libto = l;


%Macro get_data(n,index);  

     /*n: is a counting macro variable representing the lower limit of the number of CSV files
 to be read into SAS. Index: is a variable that can be thought of as 
observation number( row number) representing the upper limit 
of the number  of CSV files to be read into SAS.*/

%DO %WHILE (&n <=&index);
data _NULL_;
set &libto..&dsname end=last;
if _N_ =&n then Do;
call symput('path',path);      /*  Get file path from CSV_files*/
call symput('dsn',name);       /* Get dataset name from CSV_files*/                     
if not last  then index+1;     /* Create macro variable Index */
else if last then call symput ('index',index);  
End;
run;

proc import datafile= "&path"             
     out= &libto..&dsn
     dbms=dlm
     replace;
     delimiter=","  ;            
     getnames=yes;
run;
%End;

%Mend get_data;

/* Macro Call*/
%get_data(1,4);

When I execute this Macro I always iterate over the first observation (in this case AAPL). It simply imports the aapl.csv file over and over....what's wrong?

UPDATE

Following the suggestion of Dmitry Shopin I changed my while for a do loop:

%let dsname = csv_files;                                                   
%let libto = l;

%Macro get_data(n,index);       
%let dsname = csv_files;                                                   
%let libto = l;

%do i=&n %to &index;
data _NULL_;
set &libto..&dsname end=last;
if _N_ =&i then Do;
call symput('path',path);      /*  Get file path from CSV_files*/
call symput('dsn',name);       /* Get dataset name from CSV_files*/                     
if not last  then index+1;     /* Create macro variable Index */
else if last then call symput ('index',index);  
End;
run;

proc import datafile= "&path"             
     out= &libto..&dsn
     dbms=dlm
     replace;
     delimiter=","  ;            
     getnames=yes;
run;
%End;
%End;

%Mend get_data;

/* Macro Call*/
%get_data(1,4);

The errors that I get is the following:

ERROR 180-322: Statement is not valid or it is used out of proper order.

I get this for multiple lines in the code but generates the last 3 out of 4 SAS datasets from my CSV files.

I also get the error for the &dsn in the code:

ERROR 22-322: Syntax error, expecting one of the following: ;, (, DATAFILE, DATATABLE, DBMS,
          DEBUG, FILE, OUT, REPLACE, TABLE, _DEBUG_.

回答1:


Maybe, it's because you don't increment your &n macrovariable with every iteration? I would suggest to replace your

%DO %WHILE...

loop with

 %DO i=&n %TO &index;
...
if _N_=&i then ...;

UPDATE

This is what I run and it worked. It's exactly the same updated code from your question, except:

-I added data step to create csv_files dataset

-I deleted the second %END statement

-added LIBNAME to assign l library

-changed F:-drive to C:-drive in the paths (just because I don't have F-drive):

libname l 'C:\Data';

data l.csv_files;
    length name $4 path $20;
    input name $ path $;
datalines;
aapl C:\Data\aapl.csv
msft C:\Data\msft.csv
ibm C:\Data\ibm.csv
goog C:\Data\goog.csv
;
run;

%let dsname = csv_files;                                                   
%let libto = l;

%Macro get_data(n,index);       
%let dsname = csv_files;                                                   
%let libto = l;

%do i=&n %to &index;
    data _NULL_;
        set &libto..&dsname end=last;
        if _N_ =&i then Do;
            call symput('path',path);      /*  Get file path from CSV_files*/
            call symput('dsn',name);       /* Get dataset name from CSV_files*/                     
            if not last  then index+1;     /* Create macro variable Index */
            else if last then call symput ('index',index);  
        End;
    run;

    proc import datafile= "&path"             
        out= &libto..&dsn
        dbms=dlm
        replace;
        delimiter=","  ;            
        getnames=yes;
    run;
%End;

%Mend get_data;

/* Macro Call*/
%get_data(1,4);



回答2:


If you just want to read them into a SAS data set, you could try using the FILEVAR= option in the infile statement. FILEVAR can read multiple external files when you know their path.

data files;
    length path $40;
    input name $ path $;
    datalines;
    sample1 C:\sasdata\sample1.csv 
    sample2 C:\sasdata\sample2.csv
    test C:\Cstuff\test.csv
    ;
run;

data want(drop=name);
     set files;
     infile dummy filevar=path DLM=',' length=reclen end=done missover;
     do while (not done);
        input A B C;
        output;
     end;
run;



回答3:


While fooling around with the code I found a way to get all four csv files imported in SAS using while I have no clue why this works relatively to what I did before with either the DO or While

options symbolgen mlogic nomprint;  


%let dsname = csv_files;                                                   
%let libto = l;
libname l 'C:\SASDATA\';

%Macro get_data(n,index);       

%IF &n <= &index %then %Do;

%DO %WHILE (&n <=&index);

data _NULL_;
set l.csv_files end=last;
if _N_ =&n then Do;
call symput('path',Path);                /*  Get file path from Datalog*/
call symput('dsn',Name);       /* Get dataset name from Datalog*/                       
if not last  then index+1;                 /* Create macro variable Index */
else if last then call symput ('index',index);  
End;
run;

proc import datafile= "&path"             
     out= &libto..&dsn
     dbms=dlm
     replace;
     delimiter=","  ;            
     getnames=yes;
run;


%End;
%End;

Data _NULL_;
set &libto..&dsname;
%IF &n gt &Index %then %Put ERROR Ending execution: Check values of n and Index (n must be less than or equal to index);
run;
%Mend get_data;

/* Macro Call*/

%get_data(1,1,4);


来源:https://stackoverflow.com/questions/20834839/sas-do-while-loop-not-iterating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!