BookmarkSubscribeRSS Feed
msg
Calcite | Level 5 msg
Calcite | Level 5
Hi all,

I have a request to create variables in a dataset depends on the number of words a particular string has. I came with this code, but its not working.

For. Ex. The string "name" has 5 words, so my dataset one should have 5 variables starting with word1 till word5 containing the corresponding words.

%macro split (name=);
data one;

%let i=1;
j='x';
%do %while (j ne ' ');
word&i=%scan(&name,&i,' ');
j=word&i.;
output;
%let i=%eval (&i. + 1);
j=%scan(&name,&i,' ');
%end;

run;
%mend split;

%split (name='sas is an analytical language');

What may be the error in this code?
10 REPLIES 10
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You are mixing DATA step processing with SAS macro processing. A macro is normally resolved at compilation time. Your macro construct should be using all DATA step code (SAS variables, not SAS macro variables). Also, you will need to address the consideration of SAS variable length as you parse your input SAS variable -- defining a SAS LENGTH statement for your temporary variable - shown as "j". Lastly, your code generates one or more observations, depending on the input variable contents -- so you are actually generating an observation for each parsed sub-variable field/value.

Better to define what you want to actually accomplish showing both INPUT data and the desired OUTPUT data -- then others on the forum can provide feedback.

Scott Barry
SBBWorks, Inc.
msg
Calcite | Level 5 msg
Calcite | Level 5
Okay.

The input is a string "sas is an analytical language".

The output should be 5 variables (dynamically) such as

Word1 Word2 Word3 Word4 Word5
--------- ------------ ----------- ----------- --------------
sas is an analytical language

Hope my request is clear.
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You can still use macro language logic but with SAS DATA step functions to parse your input variable, creating one or more "parsed data" variables, very similar to what you have shown in your code. Suggest you give it a try (coding a SAS macro to work within a DATA step), test it, and then come back to the forum, if you have unexpected results. Again, you will need to consider the SAS LENGTH attribute for each new variable - also you will have some challenges determining how many new SAS variables to declare, if you do not know the number of sub-string components that are present in your INPUT variable. Possibly you can look to use a SAS CALL SYMPUT when you have completed the parsing logic, setting a macro variable identifying number of words in your input variable. Investigate using the COUNTW function to determine your DO/END loop for the parsing process.

Scott Barry
SBBWorks, Inc.
Paige
Quartz | Level 8
%let string=sas is an analytical language;
%let nwords=%word_count2(&string);

The word_count2 macro is given at http://support.sas.com/kb/26/152.html
then you write a loop

inside the loop

%let word&i = %scan(&string,&i,%str( ));
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
As I read the details (beyond the SUBJECT), the OP posted a question about parsing a SAS dataset variable, not a SAS macro variable.

Scott Barry
SBBWorks, Inc.
ChrisNZ
Tourmaline | Level 20
Msg, think of the macro language as a code generator.

The OP posted a question about parsing a macro variable into SAS dataset variables as I understand it.
[pre]
%macro split (name=);
data one;
%do i=1 %to %sysfunc(countw(&name));
word&i = "%scan(&name,&i)";
%end;
run;
%mend split;
%split (name=sas is an analytical language)
[/pre]
or even all the logic in the data step:
[pre]
%macro split (name=);
%let countw=%sysfunc(countw(&name));
data one(drop=i);
array word(&countw) $16;
do i=1 to &countw;
word[ i] = scan("&name",i);
end;
run;
%mend split;

%split (name=sas is an analytical language)
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
I believe that we are working with output SAS variables; I noticed an OUTPUT statement in the original post which persuaded my feedback. Maybe the OP needs to reconsider the basis of the post to contribute some different code -- better yet, start a new thread, when there is a problem / question on the topic point?

Scott Barry
SBBWorks, Inc.
msg
Calcite | Level 5 msg
Calcite | Level 5
Thank you all for your suggestions. I will take a look and try today.

Mine is SAS 8.2 and doesn't support COUNTW function.
DanielSantos
Barite | Level 11
OK then, you should use tho "old fashion way" word parsing.

Just do the following modification to Chris code:

%macro split (name=);
data one;
%let I=1;
%do %until(%scan(&name,&I) eq );
word&i = "%scan(&name,&I)";
%let I=%eval(&I+1);
%end;
run;
%mend split;
%split (name=sas is an analytical language);

Cheers from Portugal.

Daniel Santos @ www.cgd.pt.
msg
Calcite | Level 5 msg
Calcite | Level 5
Thanks all for ur explanations. I got confused with the intreaction between macro and the data step. Now, it's fine. Thanks again.

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
  • 10 replies
  • 9705 views
  • 0 likes
  • 5 in conversation