BookmarkSubscribeRSS Feed
BayleyVos
Calcite | Level 5

If have a data set "branch_list_mod" - which is a column of values that I am trying to match to.

Then I have data set "NA_PACC_Responses" - which has a column "message_mod" that I am trying to match to the "branch_list_der".

 

The "message_mod" is an incoming text message (so free text) that needs to be matched to a list of accepted responses.

 

I do this by a similarity macro, as follows:

 

 

%macro similarity (out =, text =);
	data &out. (keep = branch);
	set branch_list_mod;
		cost1 = min(250,spedis(strip(lowcase(branch_match)),&text.));
		cost2 = min(250,spedis(&text.,strip(lowcase(branch_match))));
		cost3 = max(cost1,cost2);
		if cost3 > 0 then similarity = (1 - (min(cost1,cost2)/250));
		else similarity = 1;
		if similarity > 0.9 then output;
	run;
%mend similarity;

But then when I call the function in a data step, it give me the error - more positional parameters found than defined.

 

 

Here is how I call the function:

 

 

data NA_PACC_Responses_der;
set NA_PACC_Responses (obs = 1);

	branch_der = %similarity(test1, message_mod);

run;

 

Here is an extract of the list of accepted responses (data set - branch_list_der):

 

oshikango
oshakati
rundu
ondangwa
opuwo

 

Here is an extract of the list of free text than can be received:

 

tsumeb
walvis bay
walvis bay
windhoek john meinert

 

QUESTION:

 

What am I doing wrong in the macro writing or calling that it gives the error mentioned?

7 REPLIES 7
Kurt_Bremser
Super User

Two mistakes here:

  1. (the small one) definition of the macro with named parameters, but calling it with positional parameters; use text= and out= in the macro call, or omit the equal signs in the macro definition, so the macro is defined with positional parameters only.
  2. (the big one) what happens when the macro is resolved

The code after resolving the macro would look like this:

data NA_PACC_Responses_der;
set NA_PACC_Responses (obs = 1);

	branch_der = data test1 (keep = branch);
	set branch_list_mod;
		cost1 = min(250,spedis(strip(lowcase(branch_match)),message_mod));
		cost2 = min(250,spedis(message_mod,strip(lowcase(branch_match))));
		cost3 = max(cost1,cost2);
		if cost3 > 0 then similarity = (1 - (min(cost1,cost2)/250));
		else similarity = 1;
		if similarity > 0.9 then output;
	run;

run;

and end up being one big syntax ERROR.

Keep in mind that the macro preprocessor is just a sophisticated text replacement system.

BayleyVos
Calcite | Level 5

Thank you very much for the response.

 

I can also see why I'm getting the error - because of your excellent explanation.  Thank you.

 

BUT, I don't know how to fix it - the second error you explained.

 

Could you possibly suggest a fix for the second error?

 

I would greatly appreciate it.

Kurt_Bremser
Super User

Start with working Base SAS code (step one in macro development 101):

data NA_PACC_Responses_der;
set NA_PACC_Responses (obs = 1);

	branch_der = /* insert the working BASE SAS(!) code for the calculation of branch_der from data in the first observation of NA_PACC_Responses here */;

run;

Do not use any macro statements here, not even macro variables. Just do what it takes to calculate branch_der, and keep in mind that all data you want to use for this has to somehow be present in the data step; it's either in the input dataset, or you will use literals in the code.

Once you have that working, you can start on identifying code parts that need to be made dynamic, and that's where the macro programming should start.

BayleyVos
Calcite | Level 5

Thanks again!

 

The "literals in the code" you speak of - how is that done?

Kurt_Bremser
Super User

See this:

data transformed_class;
set sashelp.class;
newage = age * 5; /* the 5 here is a numeric literal */
newname = name !! 'X'; /* the 'X' is also a literal, in this case a string literal */
run;

In other programming languages (eg PASCAL), such things are often called "constants".

PaigeMiller
Diamond | Level 26

The advice given by @Kurt_Bremser is so important that I want to repeat it.

 

First, get SAS code that works in one specific instance of your problem, and only when you have that working should you think about writing the macro to work in the general case.

--
Paige Miller
PaigeMiller
Diamond | Level 26

When you create a macro, and then run it, as you have done, the macro substitutes text into the SAS code. 

 

A trivial example:

 

%let dsn = dataset1;
proc means data = &dsn;

when run results in the following code being executed (note the text substitution)

%let dsn = dataset1;
proc means data = dataset1;

And when this text substitution happens, it must result in valid SAS code. If the SAS code produced by this text substitution is not valid SAS code and produces an error, then your code won't run.

 

In your case, when you try to run the macro %similarity inside of a data step, the result, after text substitution looks partially like this:

 

data NA_PACC_Responses_der;
    set NA_PACC_Responses (obs = 1);
    branch_der = /* the text substitution is here: */ data test1; ... run;
run;

You cannot have a data step within a data step. That is not valid SAS code. 


So you need to figure out a way to do all of these calculations in a single data step; or a way to do all of these calculations in sequential data steps.

 

As a possible way to do this in a single data step, please look at the LINK command. https://documentation.sas.com/?cdcId=pgmmvacdc&cdcVersion=9.4&docsetId=lestmtsref&docsetTarget=n132s...

 

--
Paige Miller

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 7 replies
  • 1366 views
  • 0 likes
  • 3 in conversation