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

Here is my data set:

data aaa;

infile cards missover;

input no a1 $ b1 c1 a2 $ b2 c2 a3 $ b3 c3;

cards;

1 x1 1 1 z1 2 1 y1 1 2

2 x2 1 2 y2 1 2

3 x3 2 2

;

run;

proc format;

value b1fmt 1="a" 2="b";

value c1fmt 1="m" 2="f";

run;

Here is what I want to get:

data set:

no a1 b1 c1

1 x1 a m

1 z1 b m

1 y1 a f

2 x2 a f

2 y2 a f

3 x3 b f

Following is  my code:

%macro new;

Data _1;

  array num{9,3} ;

  if _n_=1 then do z=1 to 3;

                  retain i;

                  set aaa;

   array avar{*} no b1 c1 b2 c2 b3 c3;

   %let S=3;

   %let Four=4;

                  %DO k=1%TO 3;

   i=i+1;

                  num{i,1}=avar(1);

                  num{i,3}=avar(&S);

                  num{i,4}=avar(&Four);

   S=%EVAL(&S+3);

   Four=%EVAL(&Four+3);

                  %END;

    end;

run;

%mend;

%new;

the error is :Array subscript out of range at line 3 column 45

The other problem is a1 a2 a3 is not numeric. So here in the code I did not put a1,a2,a3.   How could I solve this problem?

Also I have not use format to convert the value to 'a,b,m,f'. But I know how to convert them in the last step. So At first I need to solve above problems.

How could I do?

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User

Here's one way:

data aaa;

infile cards missover;

input no a1 $ b1 c1 a2 $ b2 c2 a3 $ b3 c3;

cards;

1 x1 1 1 z1 2 1 y1 1 2

2 x2 1 2 y2 1 2

3 x3 2 2

;

run;

proc format;

value b_fmt 1="a" 2="b";

value c_fmt 1="m" 2="f";

run;

data bbb;

set aaa;

array bc(3,2) b1 c1 b2 c2 b3 c3;

do i=1 to 3;

a=vvaluex("a"||put(i, 2. -l));

b=bc(i,1);

b_format=put(b, b_fmt.);

c=bc(i,2);

c_format=put(c, c_fmt.);

if not missing(a) then output;

end;

drop a1-a3 b1-b3 c1-c3 i;

run;

View solution in original post

9 REPLIES 9
Reeza
Super User

Is that a simplified form of your data? Do you expect more occurrences of a/b/c?

In that simple form there are easier methods.

ballardw
Super User

Your out of bounds is coming because you define the array

array num{9,3} ; which says in effect each row has 3 elements

but you use:

num{i,1}=avar(1);

                  num{i,3}=avar(&S);

                  num{i,4}=avar(&Four); < the 4 is larger than the 3 defined above.

You may have meant to use

num{i,1}=avar(1);

                  num{i,2}=avar(&S);

                  num{i,3}=avar(&Four);

The DATA step variable S is not the Same as the macro variable &S.

I recommend that you also remove all of the macro variables within the data step as I don't think any of them are doing what you want. They should all be data step variables.

Also the loop

%DO k=1%TO 3;

will just generate the code within it 3 times without change and also doesn't need to be a macro loop at all.

cecily
Calcite | Level 5

now I have changed the array. But it still says 'Array subscript out of range'

ballardw
Super User

You may want to show your complete new code.

cecily
Calcite | Level 5

%macro new;

Data _1;

  array num{9,3} ;

  if _n_=1 then do z=1 to 3;

                  retain i;

                  set aaa;

   array avar{*} no b1 c1 b2 c2 b3 c3;

   %let S=3;

   %let Four=4;

                  %DO k=1%TO 3;

   i=i+1;

                  num{i,1}=avar(1);

                  num{i,2}=avar(&S);

                  num{i,3}=avar(&Four);

   S=%EVAL(&S+3);

   Four=%EVAL(&Four+3);

                  %END;

    end;

run;

%mend;

%new;

It is my new code...But that error still occurs

Reeza
Super User

Here's one way:

data aaa;

infile cards missover;

input no a1 $ b1 c1 a2 $ b2 c2 a3 $ b3 c3;

cards;

1 x1 1 1 z1 2 1 y1 1 2

2 x2 1 2 y2 1 2

3 x3 2 2

;

run;

proc format;

value b_fmt 1="a" 2="b";

value c_fmt 1="m" 2="f";

run;

data bbb;

set aaa;

array bc(3,2) b1 c1 b2 c2 b3 c3;

do i=1 to 3;

a=vvaluex("a"||put(i, 2. -l));

b=bc(i,1);

b_format=put(b, b_fmt.);

c=bc(i,2);

c_format=put(c, c_fmt.);

if not missing(a) then output;

end;

drop a1-a3 b1-b3 c1-c3 i;

run;

cecily
Calcite | Level 5

oh...thank you! That is what I want to get.

I have an another small question.

put(i, 2. -l)

Here....'-l'  why do you use this? What is the meaning of it? Could  you tell me?

Reeza
Super User

It tells SAS to left align the number when it does the conversion. If the number is less than the format length you'll end up with extra spaces in the new variable, ie a1 would be "a 1" otherwise.

data have;

set sashelp.class;

age_char="a"||put(age, 8.);

age_char2="a"||put(age, 8. -l);

run;

proc print data=have (obs=4);

var age_char age_char2;

run;

cecily
Calcite | Level 5

Thank you!

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!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

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
  • 9 replies
  • 1921 views
  • 3 likes
  • 3 in conversation