BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Imroze
Fluorite | Level 6

HI

I have two different datasets where I want to identify the matching values .

 

For example in the below code I have used both similar datasets (in real both are different). Here I would like to get local as the macro variable but uanble to graple the value with in one call. could any one please help me how to resolve macro variable by calling a macro from datastep.

 

%global temp;

%let temp = %str(std='yes');

%macro test(name);

data _null_;

set sashelp.class;

if name=&name then do;

call symput("temp",%str(local='yes'));

stop;

end;

%mend;

data xyz;

set sashelp.class;

call execute('%test('||name||')');

&temp;

run;

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

One way to code such a test is to take advantage of the CANCEL option on the RUN statement. So first create an empty macro variable and then while reading the first file conditionally set the macro variable to contain the keyword CANCEL.  Then reference the macro variable in the second data step that reads the second data file.

 

%let run_cancel=;
data _null_;
   infile 'file1' ;
   input;
   if _infile_=: 'RSS' then do;
      call symputx('run_cancel','cancel');
      stop;
  end;
run;
data want ;
   infile 'file2' ;
   input ....... ;
run &run_cancel ;

View solution in original post

17 REPLIES 17
Haikuo
Onyx | Level 15

Check SYMGET() or RESOLVE().

Imroze
Fluorite | Level 6

did not resolve my issue, if possible could you please try the sample code.

Haikuo
Onyx | Level 15
Your description need be elaborated more. There are more than one macro variables in your code, please comment your code in detail, so that people can know where/what/how, then we start from there.
Tom
Super User Tom
Super User

You should use PROC COMPARE to compare datasets.  

 

As to your posted code if you just look at the SAS log it will be obvious what is happening and why that method is not very useful.

 

First the data set XYZ is created and then there are 19 more data steps that are generated by your CALL EXECUTE() statement that are run.  This is becuase the CALL EXECUTE function just pushes code onto the stack to be executed after the current data step finishes.

 

Also notice that the data set XYZ will have the variable STD set to 'yes' since when that data step was prepared for execution the value of the TEMP macro variable was std='yes'.  So your data step is resolves to:

 

data xyz;
  set sashelp.class;
  call execute('%test('||name||')');
  std='yes';
run

Now the CALL EXECUTE will run the %TEST() macro and push any code that it generates onto the stack so that it can execute after the XYZ dataset is created.  So for example it will push code like this data step.

 

data _null_;
  set sashelp.class;
  if name=Alfred then do;
    call symput("temp",local='yes');
    stop; 
  end;

In addition to problem of the code running after the XYZ step is finished there are other problems with this code. First there is no variable named ALFRED in the SASHELP.CLASS dataset. I assume that you intended to generate "Alfred" instead so that it would be interpreted as a string literal instead of a variable name.  So the IF statement is never true so the CALL SYMPUT() function never runs.  But  note that it also has trouble since you are referencing the variable LOCAL which does not exist. Since this will never be equal to 'yes' the CALL SYMPUT statement would have always set the macro variable TEMP to the number zero converted to a text string using the BEST12. format, so eleven spaces followed by the digit 0.  Also notice that your generated code does not contain a 'RUN;' statement to terminate the data step.

Babloo
Rhodochrosite | Level 12

Could you please tell me how the call execute will work in the code below? I know that it will call the 'test' macro , but I don't understand the other thing which is enclosed in single quotes '||name||'

 

 

data xyz;
  set sashelp.class;
  call execute('%test('||name||')');
  std='yes';
run

 

Thanks in advance!

 

Tom
Super User Tom
Super User

|| is the concatenation operator.  So '%test(' || name || ')' says to sandwich the value of the variable NAME between the two string literals. So it if the value of NAME is 'Alfred  ' then the string passed to CALL EXECUTE will be '%test(Alfred  )'.  Now that SAS has introduced the CAT... series of functions I find that I use them more often than the simple concatenation operator.  So you could use CATS('%test(',name,')') instead.  Note that the CATS() function will also trim the trailing spaces from the value of the NAME variable.

 

If you use this syntax then the %TEST() macro call will execute immediately and any SAS code it generates will be pushed onto the stack to run after the current data step finishes.  But any macro code that the macro has will execute immediately.  That is why normally it is helpful to add %NRSTR() macro function around the macro call to prevent the macro from executing immediately.  Instead the macro all will be placed on the stack and then the macro will execute after the current data step finishes.

 

data xyz;
  set sashelp.class;
  call execute('%nrstr(%test)('||name||')');
  std='yes';
run
Imroze
Fluorite | Level 6

Hi Babloo,

 

the enclosed one is a parameter to the macro.

Example: If you want to pass some value to the macro then you can pass the variable value in it for each observation.

if you have a dataset with name as the variable name (4 names) then all four times it will pass and call the calling macro.

 

data test;

  input name $;

  datalines;

  kumar

  akash

  vinay

  babloo

;

 

%macro printmacro(name);

  %put These are very good guys : &name.;

%mend;

 

data _null_;

  set test;

  call execute('%test('||name||');

run;

Here the print macro  will be called 4 times (as many observations as test dataset has) and prints the output to the log.

 

Hope answered the question.

ballardw
Super User

Here's one way to find if a specific value occurs in a data set for a variable:

 

proc sql noprint;
   select (count(name)>0) into : temp
   from sashelp.class
   where name="&name";
quit;

The macro variable temp will have a value of 1 (found) or 0 (not found). Note that just as your attempted code would not match ALFRED to Alfred, case or leading spaces will not match. You might want to consider addressing those points for your application.

 

Tom
Super User Tom
Super User

If you just want to match records on value of a variable then use a MERGE statement.

 

data want ;
    merge one two ;
    by id;
run;
Imroze
Fluorite | Level 6

Thank you for the replies. well I have a confusion of how call execute works. My issue is to restrict the reading of text file based on condtion (so I created a macro and a sample example).

 

For example:

I have to read a text file

 

filename in "c:/temp.txt";

data test;

  infile in truncover;

  input  x $500.;

  if x > 'some value then only i need to create dataset or else discard reading the file';

/*Here i might need previous observations if this condition is true */

/*Value of x may come in nth row */

run;

 

data test;

infile in truncover;

Tom
Super User Tom
Super User

Is this the same problem or a new one?

Not much way to do this without reading the file twice. Once to determine if the problem value exists and then again to generate the dataset.  Or you might actually be able to use CALL EXECUTE for this problem by creating the dataset and then conditionally deleting it (or perhaps renaming it).

 

data WANT;
  infile "c:\temp.txt" truncover;
  input x $500.;
  if x > 'some value then only i need to create dataset or else discard reading the file' then do;
    call execute('proc delete data=WANT;run;');
    stop;
  end;
run;
Imroze
Fluorite | Level 6

Thanks tom,

 

Its the same issue which I posted . I had some logic running and was not working in between to solve reading text file.

 

 

 

 

Imroze
Fluorite | Level 6

want to add few more points

1. I thought to create a flag (retain varialbe) and continue reading the text file.

2. text file reading has many conditions and want to improve performance.

 

if there is any other solution to read a text file (optimized way, as it got 100's of condtions in it)

Tom
Super User Tom
Super User

In general if the question is how to read a complicated text file into a nice structured data set then conditional programming is the answer and not generated code.  Figure out a data structure that can store the information and then write a data step (or series of steps) to create that structure from the source file.  For example look at this posting on Stack Overflow.  https://stackoverflow.com/questions/34533980/reading-hierarchicalish-data-into-sas/34547963#34547963

 

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
  • 17 replies
  • 1728 views
  • 2 likes
  • 5 in conversation