BookmarkSubscribeRSS Feed
DipeshGupta
Calcite | Level 5

i am facing a problem as I tryiing to make a string by using SAS Macro and SAS functions but am not able to deal with parentheses as a string. Don't know what to do.

Can someone please help me with this.

 

My Code :

 

%MACRO MA_STRING(D,N) ;

%LET MA_STRING = %NRSTR(sum%() ;

%PUT &MA_String ;

%DO I = 1 %TO &N ;

%LET MA_STRING = %SYSFUNC(CAT(&MA_String ,%STR(,) , LAG , &I , %Str(%() , &D , %Str(%)) ));

%PUT &MA_String ;

%END ;

%MEND ;

 

%MA_STRING(P,3) ;

 

 

This is the error received.

 

sum(
ERROR: Required operator not found in expression: )
sum(,LAG1.P)
ERROR: Required operator not found in expression: sum(,LAG1.P)
ERROR: Required operator not found in expression: )
sum(,LAG1.P),LAG2.P)
ERROR: Expected close parenthesis after macro function invocation not found.
LAG , 3 , ( , P , ) ))

 

13 REPLIES 13
ballardw
Super User

It really helps to describe what you are attempting to do. And provide examples of input and desired output.

 

And when working with macros an example of the code that worked without any macro elements.

Patrick
Opal | Level 21

@DipeshGupta

As @ballardw please explain what you're trying to do and provide sample data.

On top of this: SAS Macro code generates SAS code. It appears you're trying to generate SAS code which contains the LAG() function. If so then the LAG() function must be used in a SAS Data step and you certainly can't call the macro outside of a SAS data step.

 

Astounding
PROC Star

Notice you have additional problems besides the parenthesis.  The code you are trying to create cannot run, since even if it worked you would end up with:

 

sum(,lag1(P), lag2(P))

 

The first item to sum isn't specified.

 

This might work or might not.  I just can't test it right now:

 

%LET MA_STRING=sum(  

     %do i=1 %to &n;

         lag&i(&d)

         %if &i < &n %then ,;

      %end;

   );

 

But even if it does work, it would be cleaner and more flexible to get rid of the %LET piece.

 

%macro MA_STRING (D, N);

 

   %local i;

   sum(  

 

   %do i=1 %to &n;  

      lag&i(&d)  

      %if &i < &n %then ,;

   %end;

    )

 

%mend MA_STRING;

 

Then within a DATA step you could call the macro to assign a value to a DATA step variable:

 

MA_STRING = %MA_STRING(P,3);

 

Notice that you are not locked in to using MA_STRING as the name of the variable being assigned a value.

WarrenKuhfeld
Rhodochrosite | Level 12

The best place to do string processing is in a DATA step.  Then you can use regular string functions with no worries about quoting, etc.  When you are done, you can use SYMPUTX if necessary to make a macro variable.

DipeshGupta
Calcite | Level 5

@Astounding This code worked successfully.

%macro MA_STRING (D, N);

 

   %local i;

   sum(  

 

   %do i=1 %to &n;  

      lag&i(&d)  

      %if &i < &n %then ,;

   %end;

    )

 

%mend MA_STRING;

 

Then within a DATA step you could call the macro to assign a value to a DATA step variable:

 

MA_STRING = %MA_STRING(P,3);

 

 

 

 

Is there a macro code to make a dataset from the string values.

 

eg my string is :

 

Bat Ball Apple

 

now I want something like this

 

Colname No.

Bat          1

Ball          2

Apple      3

 

 

What I am doing is I am creating a dataset for each word and then merging all the three datasets into one but I was wondering if there

is some other way so that I dont have to create a dataset for each word because it is taking a lot of memory.

Astounding
PROC Star

Of course SAS can do that.  But I'm tempted to say that you would probably be better off starting over again, and reconsidering your approach.  It sounds like you are jumping through hoops, making an easy process complicated.  If you were to post a separate question showing your original starting point, you could get some guidance on that.

 

You don't say whether your incoming string is contained in a macro variable or in a DATA step character variable.  The answer would be slightly different, but would essentially use the same tools.  The output you are showing would be a SAS data set regardless.  So assuming the original string is a macro variable:

 

data want;

length colname $ 32;

do number = 1 to countw("&string");

   colname = scan("&string", number, ' ');

   output;

end;

run;

DipeshGupta
Calcite | Level 5

@Astounding Thanks for all your help, really appreciate it and I think  I got both your codes.

 

In the first code where we are making a string using macro,

 

What we are basically doing here is, when we give a statement in a macro withour referencing it to anything else then it is taken as the output of the macro so we can use it in a datastep using %jj(i,3) and it give the value which is wriiten directly in a macro whithout any reference.

 

In the second code where we are making a dataset using string,

 

What solved my problem here is the small output command you mentioned in you code because I was facing the issue of colname being overwriiten everytime the code runs and the final output was only showing the last word of the string but now with the output statement you resolved this issue also.

 

 

And now I can't help it from being a little greedy and want to ask for a help once again.

 

Suppose I have a dataset in this format.

 

ClassA      Subjects     Marks

Rahul        Maths         95

Raj            English       75

John          Accounts    97

 

And I want a dataset something like this.

 

Category     Value

ClassA         Rahul

ClassA         Raj

ClassA         John

Subjects       Maths

Subjects       English

Subjects       Accounts

Marks            95

Marks            75

Marks            97

 

Now what I am doing is I am using Proc sort with nodupkey for each column and creating a dataset for each column i.e. ClasssA Subjects Marks. eg of a data set.

 

Category     Value

ClassA         Rahul

ClassA         Raj

ClassA         John

 

Then I am merging three datasets together.

 

Is there a short method for this task also.

Astounding
PROC Star

Given that you know the variable names, it's straightforward.  You may need to ignore some messages about numeric to character conversion.

 

data want (keep=category value order);

set have;

length category value $ 20;

order=1;

category='ClassA';

value = ClassA;

output;

order=2;

category='Subjects';

value = Subjects;

output;

order=3;

category = 'Marks';

value = left(marks);

output;

run;

 

proc sort data=want;

by order;

run;

 

Still, I doubt the wisdom of doing this. If the data ever gets sorted differently, you can lose the relationship between the class, the subject, and the mark.

 

DipeshGupta
Calcite | Level 5

@Astounding But your code will paste all the column values and I want only the unique values of the column.

Patrick
Opal | Level 21

@DipeshGupta

"Then I am merging three datasets together."

The way I understand what you describe and given your sample data you would end up where you've started from after this merge.

 

The sample data you provide is already unique per row. It's also not really clear from your description if you're after unique rows or after unique values per variable. If it's after unique values per variables then I don't understand what you're trying to merge together as you'll loose the connection between the values (i.e. that it was Rahul who had a mark of 95 in maths).

Can you please explain a bit better and most importantly provide better sample data which demonstrates what you're after.

Astounding
PROC Star

Then you'll have to show a more specific example ... one that actually starts with duplicates and what the end result should look like.  You could easily end up with more observations for MARKS than for SUBJECTS in the final data set.  It's possible that what you are doing now is just fine.  It's also possible that maintaining the order (as my program did) is not important.  There are just too many guesses when these cases aren't illustrated and the final result should be "something like" the illustrated result.

ShiroAmada
Lapis Lazuli | Level 10

%MACRO MA_STRING(D,N) ;

%LET MA_STRING = %NRSTR(sum%() );

%PUT &MA_String ;

%DO I = 1 %TO &N ;

%LET MA_STRING = %SYSFUNC(CAT(&MA_String ,%STR(,) , LAG , &I , %Str(%() , &D , %Str(%)) ));

%PUT &MA_String ;

%END ;

%MEND ;

 

%MA_STRING(P,3) ;

 

I think that is the problem.

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!

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 13 replies
  • 5706 views
  • 3 likes
  • 7 in conversation