BookmarkSubscribeRSS Feed
_LB
Fluorite | Level 6 _LB
Fluorite | Level 6
Hello all;
I have seen this before, but can't figure this out where you have a dataset such as:

data x;
input x $ 1-3 com $ 5;
datalines;
_01 y
_02 y
_03 n
_04 y
;
run;

where for example, com=y then the observation would be _01_Y=1;
I have numerous values so I don't wish to recode these as
_01_Y, 01_N..._100_Y

I have tried different iterations but I do not get the correct outcome,
many thanks.

Lawrence




if com='y' then call symput('x'||left(x),(compress(x||'_Y')));
if com='y' then &x=1;
10 REPLIES 10
sbb
Lapis Lazuli | Level 10 sbb
Lapis Lazuli | Level 10
You are mixing macro language with a DATA step's SAS variable assignment. It appears you are attempting (want to) count with SAS variable X as in:

X + 1;

Also, if you want the value of SAS variable "com" to be concatenated as part of the macro variable x1, x2, x3, etc., then you must include that variable as part of the argument2 in your SYMPUT call.

Suggest you add some PUTLOG _ALL_; diagnostic command(s) to your DATA step, and also add %PUT _USER_; to your SAS program to display your global macro variable values at the end of your DATA step.

Remember, the macro language process, normally, resolves at compilation time so you need to keep the two separate - that is, the DATA step logic using SAS variables/columns and any macro language components separate, where appopriate.

Also, turning on the macro compilation and macro variable compilation will get you more diagnostics to help you debug your program - such as:

OPTIONS SOURCE SOURCE2 MACROGEN SYMBOLGEN MPRINT /* MLOGIC */ ;

Scott Barry
SBBWorks, Inc.



Scott Barry
SBBWorks, Inc.

Suggested Google advanced search arguments, this topic / post:

data step symput macro variable site:sas.com

macro variable introduction site:sas.com

macro language introduction site:sas.com
Cynthia_sas
SAS Super FREQ
Hi:
You cannot create &X and then use &X in the same DATA step program as you show in this snippet of code:
[pre]
if com='y' then call symput('x'||left(x),(compress(x||'_Y')));
if com='y' then &x=1;
[/pre]

So, if you create &X with the CALL SYMPUT statement, you must have a step boundary before the use of &X as described in this Tech Support note:
http://support.sas.com/kb/23/182.html

What is not clear to me is what the desired final dataset would look like. Would you have 1 observation with multiple variables??
[pre]
Variable names: _01_Y _02_Y _03_N _04_Y
Variable values: 1 1 1 1
(all on one observation???)
[/pre]

OR, would you have an obs for every obs in your original dataset:
[pre]
New_X New_value (variable names)
_01_Y 1 <--variable values
_02_Y 1 <--variable values
_03_N 1 <--variable values
_04_Y 1 <--variable values
(with 4 observations and the VALUE of X would be recoded to be the new value??)
[/pre]

OR, would you have 8 observations for your original 4 datalines:
[pre]
New_X New_value (variable names)
_01_Y 1 <--variable values based on value of COM
_01_N 0 <--added obs for _01_N = 0
_02_Y 1 <--variable values based on value of COM
_02_N 0 <--added obs for _02_N = 0
_03_N 1 <--variable values based on value of COM
_03_Y 0 <--added obs for _03_Y = 0
_04_Y 1 <--variable values based on value of COM
_04_N 0 <--added obs for _04_N = 0
(with 8 observations -- a Y and N for each value of X.)
[/pre]

cynthia
_LB
Fluorite | Level 6 _LB
Fluorite | Level 6
Thanks Cynthia for the tip. I was simply trying to recode this in such a way that it creates a new variable as I have 20 some job classifications so that in the end..

_01_Y _01_N
ob1 1
ob2 1
ob2 1
...
obs20 1

This data will then be transposed. I am just trying to figure out a way so that I can convert
the data strings such as _17_Y to a variable field if this helps w/o needing to create each one. I can do an entire macro to do this for each number but it gets complicated remerging sets but can be done. I was looking for an easier solution w/in the data set. it does not have to be a macro.

hope this helps explain my dilemma.
Thanks again.

Lawrence
Peter_C
Rhodochrosite | Level 12
> Thanks Cynthia for the tip. I was simply trying to
> recode this in such a way that it creates a new
> variable as I have 20 some job classifications so

> an entire macro to do this for each number but it
> gets complicated remerging sets but can be done. I
> was looking for an easier solution w/in the data set.
> it does not have to be a macro.
>

Lawrence

seriously, consider not creating new variables, but instead, create one new variable which would hold "job classification"
Then instead of 20 columns for each type of job information, you hold only one.
Analysing by "job classification" is natural with SAS reporting procedures - by using what are called CLASS variables and statements.

good luck
peterC
_LB
Fluorite | Level 6 _LB
Fluorite | Level 6
Peter;
I know where you are going with this I think. Something to ponder the next time I have to do this more efficiently.
In the interim, I simply parsed out a subset, ran a macro, and re-merged later.

For all though, I do appreciate all the tips.
Best

Lawrence

%macro group_roles (data=, var=);
proc sort data=&data(keep=&var) out=values nodupkey;
by &var;
run;
data _null_;
set values end=last;
call symputx('GROUP'||left(_n_),&var);
if last then call symputx('count',_n_, 'g');
run;
%put _local_;


DATA _NULL_ ;
select(&var);
%do i=1 %to &count;

DATA GROUP&i;
SET PREP_ROLES;
where role2="&&GROUP&i";
IF SUBSTR(COMPLIANCE,1,1)='1' THEN &&GROUP&i.._YES=1;
IF SUBSTR(COMPLIANCE,1,1)='2' THEN &&GROUP&i.._NO=1;
run;


%END;

%mend group_roles;
%group_roles(data=roles, var=role2);
art297
Opal | Level 21
LB,

I don't know enough about your problem to know whether the following is relevant but, a few years ago, datanull proposed a solution for a problem that I thought could only be solved with macro variables.

Thus, my suggestion is simply to read the following SAS-L thread:
http://groups.google.com/group/comp.soft-sys.sas/browse_thread/thread/19c742867a27cbb1/4999ff4a5a3cd6ad?q=putn+tabachneck+datanull+group:comp.soft-sys.sas

If it helps you solved your problem, case solved! If not, it should provide some useful tools for solving other problems.

Art
chang_y_chung_hotmail_com
Obsidian | Level 7
We are not communicating each other because your usage of the technical terms like observation, recode, iterations does not seem to be correct, leaving too much room for different interpretations.

Here is mine. I assume a situation where you ask four yes/no questions to two respondents and what you want to do is to create 8 dummy (or 1/0) variables for each respondent, given an input data with four observations per respondent. If this is the case, then you can do something like below. Hope this helps at bit
[pre]
/* test data. two respondents answering 4 yes/no questions each */
data qs;
input id q $ ans $;
datalines;
1 q01 y
1 q02 y
1 q03 n
1 q04 y
2 q01 n
2 q02 y
2 q03 n
2 q04 y
;
run;

/* for each input obs, output two. one with the given answer
another with its complement */
data temp;
set qs;
_name_ = catx("_", q, ans);
val = 1;
output;
ans = ifc(ans="y", "n", "y");
_name_ = catx("_", q, ans);
val = 0;
output;
run;

proc sort data=temp;
by id _name_;
run;

/* then reshape to wide */
proc transpose data=temp out=rs(drop=_:);
var val;
by id;
run;

/* check */
proc print data=rs noobs;
run;
/* on lst
id q01_y q01_n q02_y q02_n q03_n q03_y q04_y q04_n

1 1 0 1 0 1 0 1 0
2 0 1 1 0 1 0 1 0
*/
[/pre]
_LB
Fluorite | Level 6 _LB
Fluorite | Level 6
Chang;
I am going to try your solution now...
SUN59338
Obsidian | Level 7
how about this macro?

data test;
input x $ 1-3 com $ 5;
datalines;
_01 y
_02 y
_03 n
_04 y
;
run;

%macro macro_test;

proc sql noprint;
select strip(x)||strip(com) into: newvars separated by ' '
from test;
%let nvar=&sqlobs;
quit;


proc format lib=work;
value $vn
%do i=1 %to &nvar;
"%scan(&newvars,&i)"=&i
%end;
;
run;

data result;
set test;
array newv(&nvar) &newvars;
newv(put(strip(x)||strip(com),$vn.))=1;
run;
%mend;
%macro_test
ChrisNZ
Tourmaline | Level 20
LB, you can't create dataset variables during data step execution. Variables are determined during compilation, before any data value is known.

The classic transpose way is something like:
[pre]

data TEST;
infile cards pad;
input X $6.;
X=trim(X);
VALUE=1;
datalines;
_01 y
_02 y
_03 n
_04 y
run;
proc transpose out=T;
id X ;
var VALUE;
run;
[/pre]

You can also just update the metadata rather than rewrite the whole dataset:
[pre]
data TEST;
length REN $200;
retain REN ;
drop REN X;
array XX[4] (4*1);
infile cards pad eof=LAST;
input X $6.;
REN=cats('XX',_N_,'=',compress(X))||' '||REN;
return;
LAST:
output;
call execute('proc datasets nolist;modify TEST;rename '||trim(REN)||';run;');
datalines;
_01 y
_02 y
_03 n
_04 y
run;
[/pre]

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
  • 1506 views
  • 0 likes
  • 8 in conversation