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

Hello SAS users,

 

I have 91 data sets with 1 numeric variable and at least 26 character variables per data set. I created a macro to conduct processing of all data sets. 

 

One part of my macro is not working as intended. What I want to do is to specify an array statement that references only the character variables, then use DO LOOPS to do some processing for all other character variables listed after the first character variable.

 

Below is my code:

 

/*Convert fields of item responses from character to numeric variables*/
DATA Raw.&MODULE._Examinee_Data;
SET Raw.&MODULE._Examinee_Data_POS;
ARRAY CHAR[*]  _CHARACTER_;
DO I = 2 to dim(CHAR);
IF CHAR[I] = 'A' THEN CHAR[I] = '1';
IF CHAR[I] = 'B' THEN CHAR[I] = '2';
IF CHAR[I] = 'C' THEN CHAR[I] = '3';
IF CHAR[I] = 'D' THEN CHAR[I] = '4';
IF CHAR[I] = 'E' THEN CHAR[I] = '5';
IF CHAR[I] = 'Z' THEN CHAR[I] = '0';
END;
DO J = 2 to dim(CHAR);
CHAR[J] = input(CHAR[J], 32.);
END;
RUN;

 

The problem I have is that the values for the I and J indexing variables are 2 more than the actual number of array elements processed using the DO LOOP. 

 

Data I have below - the first character variable of the array contains the text of EXAM101, and the values for the remaining character variables are listed to the right of the value for the first character variable. 

 

1228 EXAM101 A C D B Z 

 

Data I want below - the I and J indexing variables should each have values of 5, but my code results in values of 7 which is what I don't want.  

 

1228 EXAM101 1 3 4 2 0 5 5 

 

Can someone explain to me what I am doing wrong, and post a solution?

 

Thanks

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Two of those other variables must be numeric instead of character for the values of your index variables to be 5 instead of 7.

data have;
 input id name $ (v1-v5) ($);
cards;
1228 EXAM101 A C D B Z
;

data test;
  set have;
  array chars _character_;
  do i=2 to dim(chars);
  end;
run;
proc print;
run;
Obs     id      name      v1    v2    v3    v4    v5    i

 1     1228    EXAM101    A     C     D     B     Z     7

If you have 6 character variables then DIM(chars) will be 6 and I will be set to 7 after the DO loop since having a value larger than 6 is what caused the looping to stop.

View solution in original post

7 REPLIES 7
Astounding
PROC Star

First thing to learn is how a DO loop works.  Here's a test program you can run.  Once you are comfortable with the results, we can talk about fixing the program.

 

data _null_;
do i=1 to 5;
   put 'Inside:  ' i=;
end;
put 'Outside:  ' i=;
run;

data _null_;
do i=1 to 5 by 3;
   put 'Inside:  ' i=;
end;
put 'Outside:  ' i=;
run;
ADouglas
Obsidian | Level 7

Ok. I tried it. I understand how DO LOOPS work now. But, I'm not sure how the index variable has 2 more than the number of variables processed.

 

Thanks

ballardw
Super User

How about running:

 

proc contents data =  Raw.&MODULE._Examinee_Data_POS;

run;

 

and share the result.

 

You cannot change a variable type from character to numeric once it is created.

So if

DO J = 2 to dim(CHAR);
CHAR[J] = input(CHAR[J], 32.);
END;

is supposed to create numeric values it will fail. You should have a message about numeric values converted to character in the log.

Tom
Super User Tom
Super User

Two of those other variables must be numeric instead of character for the values of your index variables to be 5 instead of 7.

data have;
 input id name $ (v1-v5) ($);
cards;
1228 EXAM101 A C D B Z
;

data test;
  set have;
  array chars _character_;
  do i=2 to dim(chars);
  end;
run;
proc print;
run;
Obs     id      name      v1    v2    v3    v4    v5    i

 1     1228    EXAM101    A     C     D     B     Z     7

If you have 6 character variables then DIM(chars) will be 6 and I will be set to 7 after the DO loop since having a value larger than 6 is what caused the looping to stop.

ADouglas
Obsidian | Level 7

Thanks I forgot this detail about the indexing variable.

 

Take care,

Aaron

novinosrin
Tourmaline | Level 20
data have;
input var1 (char1-char6) ($);
cards;
1228 EXAM101 A C D B Z 
;

data want;
set have;
array c(*) _char_;
array t(5)$1;
array num(5);
temp=cats(of char2-char6);
call pokelong(temp,addrlong(t(1)),5);
call sortc( of t(*));
do i=1 to dim(num);
num(i)=whichc(c(i+1), of t(*));
end;
drop i t:;
run;
KachiM
Rhodochrosite | Level 12

I thought you want ABCDEZ to be changed to numbers as: 1,2,3,4,5,0

 

Here are two ways for doing it.

 

data have;
 input id name $ (v1-v5) ($);
cards;
1228 EXAM101 A C D B Z
1300 TEST102 Z C B D E
1400 EXAM103 A Z B C D
;
run;

data want;
   set have;
   array n[*] n1 - n5;
   array v[*] v1 - v5;
   length str $6;
   str = 'ZABCDE';
   do i = 1 to 5;
      k = findc(str, v[i]) - 1;
      n[i] = k;
   end;
drop v: i k str;
run;

 This will change v: to n:

 

If you want to rename n: to v: then it is attainable by using the RENAME as:

 

data want(rename = (n1 - n5 = v1 - v5));
   set have;
   array n[*] n1 - n5;
   array v[*] v1 - v5;
   length str $6;
   str = 'ZABCDE';
   do i = 1 to 5;
      k = findc(str, v[i]) - 1;
      n[i] = k;
   end;
drop v: i k str;
run;

Instead of FINDC() function, you can use RANK() function. 'A' will be 65, 'B' is 66 and so on. Here is the use of RANK():

 

data want(rename = (n1 - n5 = v1 - v5));
   set have;
   array n[*] n1 - n5;
   array v[*] v1 - v5;
   do i = 1 to 5;
      k = rank(v[i]) - 64;
      if k = 26 then k = 0;
      n[i] = k;
   end;
drop v: i k;
run;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 7 replies
  • 749 views
  • 2 likes
  • 6 in conversation