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

Hi,

Apologies in advance if the solution to this is ridiculously simple.

My use of SAS is in a very limited capacity.
I manage to hodge-podge programs together from SAS code I can find on the internet.

I came across this wonderful solution from @Ksharp that shows how to shift missing values
from the the right to left and it works beautifully. Unfortunately I need it to work for some
character variables. Is there any easy change that can be made to the code below to accommodate?

Thank you for any help you can offer!

 


data ja;
   infile cards firstobs=2;
   input id:$3. age ja1-ja3;
   cards;ID_ AGE Ja1 Ja2 Ja3
001 003 207 .   506
003 023 445 211 241
021 101 .   431 246
145 042 566 343 121;;;;
   run;
data want;
 set ja;
 array j{*} ja1-ja3;
 array x{3} _temporary_;
 n=0;call missing(of x{*});
 
 do i=1 to dim(j);
  if not missing(j{i}) then do;
   n+1;x{n}=j{i};
  end;
 end;
 
 do i=1 to dim(j);
  j{i}=x{i};
 end;
 
 drop i n;
run;
1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hi @TheDarkSide and welcome to the SAS Support Communities!

 

Yes, there is an easy change: Just insert a suitable length specification into the second ARRAY statement.

 

To determine the "suitable" length, you can look at PROC CONTENTS output of your dataset (let's call it "have"):

 

proc contents data=have;
run;

The output contains a table like this:

 

 

Alphabetic List of Variables and Attributes

#    Variable    Type    Len

2    age         Num       8
1    id          Char      3
3    ja1         Char      4
4    ja2         Char     10
5    ja3         Char      8

(I've made up a modified version of your example dataset with character variables ja1-ja3.)

 

Find the maximum of the lengths of the character variables in question (see column "Len" in the output). In the above example this is 10 (the maximum of 4, 10 and 8). Insert a dollar sign followed by this value (a larger value would work as well) into the second ARRAY statement:

array x{3} $10 _temporary_;

Of course, the array dimension, 3, would also need to be adapted if you had more than three character variables to be processed.

 

Please don't hesitate to ask if you have more questions. (And there's no reason to apologize for "simple" ones.)

 

Not sure why your question hadn't been answered earlier*. Maybe because your text somehow got into the code window (and didn't wrap properly because of a weakness of the forum software). But don't worry about that.

 

*EDIT: Okay, it had just been answered while I was still typing ...

View solution in original post

3 REPLIES 3
ballardw
Super User

To "shift" character variables around is basically the same but there is potential concern: the defined lengths of your existing variables.

Below is an example where the JA variables have different lengths, 5, 7 and 3 characters each. The only difference in the actual code to "shift" is that the _temporary_ array needs to be defined as character and the number of characters allowed for each element which should be longest of your character variables. Note that in this example, to demonstrate the issue with lengths that for the ID=1 record the result of the original JA2 variable gets truncated to fit in the storage defined for JA1.

data ja;
   informat ja1 $5. ja2 $7. ja3 $3.;
   input id:$3. age ja1-ja3;
   cards;
1 19 . 0034456 207 
2 20 00345 . 445 
3 21 021 101 .   
4 22 145 042 566 
;
run;
data want;
 set ja;
 array j{*} ja1-ja3;
 /* the temporary array has to have the length of each value
    the longest of any of the variables
 */
 array x{3} $ 7 _temporary_;
 n=0;call missing(of x{*});
 
 do i=1 to dim(j);
  if not missing(j{i}) then do;
   n+1;x{n}=j{i};
  end;
 end;
 
 do i=1 to dim(j);
  j{i}=x{i};
 end;
 
 drop i n;
run;

If you define all of your character variables as having the same length then there is no problem.

 

If the lower index variables are always longer than the higher index values, then there is no problem.

If there MIGHT be a problem you can assign a length value before the Set statement in the Want data step code:

 

data want;

   length ja1 - ja3 $ 7.;

   set ja;

  <other code>.

 

That will ensure that all of the JA variables in WANT have the same length and avoid the problem.

FreelanceReinh
Jade | Level 19

Hi @TheDarkSide and welcome to the SAS Support Communities!

 

Yes, there is an easy change: Just insert a suitable length specification into the second ARRAY statement.

 

To determine the "suitable" length, you can look at PROC CONTENTS output of your dataset (let's call it "have"):

 

proc contents data=have;
run;

The output contains a table like this:

 

 

Alphabetic List of Variables and Attributes

#    Variable    Type    Len

2    age         Num       8
1    id          Char      3
3    ja1         Char      4
4    ja2         Char     10
5    ja3         Char      8

(I've made up a modified version of your example dataset with character variables ja1-ja3.)

 

Find the maximum of the lengths of the character variables in question (see column "Len" in the output). In the above example this is 10 (the maximum of 4, 10 and 8). Insert a dollar sign followed by this value (a larger value would work as well) into the second ARRAY statement:

array x{3} $10 _temporary_;

Of course, the array dimension, 3, would also need to be adapted if you had more than three character variables to be processed.

 

Please don't hesitate to ask if you have more questions. (And there's no reason to apologize for "simple" ones.)

 

Not sure why your question hadn't been answered earlier*. Maybe because your text somehow got into the code window (and didn't wrap properly because of a weakness of the forum software). But don't worry about that.

 

*EDIT: Okay, it had just been answered while I was still typing ...

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 3 replies
  • 4385 views
  • 1 like
  • 3 in conversation