Hello, I would like to covert a set of numerical variables to character and replace . to "NA". I tried to use array for this task. However my missing is still show up as . in stead of "NA". What did I do wrong?
Please see the sample data and my codes below:
data df1; a = .; b=1; c=1; output; a = 1; b=.; c=1; output; a = 1; b=1; c=.; output; run; data want ; set df1; array _invars{3} a b c; array _invals{3} _inval1 _inval2 _inval3; do i=1 to 3; if _invars{i} gt .z then _invals{i}=put( _invars{i},5.2) ; else _invals{i}= "NA" ; end; run ;
You probably get notes liek this : "NOTE: Invalid numeric data, 'NA' , at line 49 column 27".
You just missed to declare the datatype of the new variables. You need a character variables, so $x needs to be declared in front of the new variables created by array.
See the below:
data want ;
set df1;
array _invars{3} a b c;
array _invals{3} $8 _inval1 _inval2 _inval3;
do i=1 to 3;
if _invars{i} gt .z then _invals{i}=put( _invars{i},5.2) ;
else _invals{i}= "NA" ;
end;
run ;
You probably get notes liek this : "NOTE: Invalid numeric data, 'NA' , at line 49 column 27".
You just missed to declare the datatype of the new variables. You need a character variables, so $x needs to be declared in front of the new variables created by array.
See the below:
data want ;
set df1;
array _invars{3} a b c;
array _invals{3} $8 _inval1 _inval2 _inval3;
do i=1 to 3;
if _invars{i} gt .z then _invals{i}=put( _invars{i},5.2) ;
else _invals{i}= "NA" ;
end;
run ;
@A_Kh Thanks for quick reply. One side question, is there a quicker method to name the new variables? In my codes, I listed
_inval1 _inval2 _inval3
Is it a way to name a set of variables with prefix _inval given we know the number of new variables=3?
You can display NA in numeric variables with missing values without converting them to character by using a custom format:
proc format;
value myMissing
low-high = [best12.]
other = 'NA'
;
run;
data MyData;
set sashelp.class;
if name in ('John','Mary') then age = .;
if Name in ('Alice','Philip') then weight = .;
format age weight MyMissing.;
run;
proc print data = MyData;
run;
I usually list variables like this:
array _invals{3} $8 _inval1 - _inval3;
or just omit new variable names when the range is specified with array name, like "_invals [3]" in this case. SAS takes new variable names from the declared array name (_invals) and creates the number of new variables equal to a specified range (3) and appends sequential numbers (eg. 1 to n.) to that.
see this :
data want ;
set df1;
array _invars{3} a b c;
array _invals{3} $8;
do i=1 to 3;
if _invars{i} gt .z then _invals{i}=put( _invars{i},5.2) ;
else _invals{i}= "NA" ;
end;
run ;
You could use a format for recoding and if only required for display (print) purposes then even apply it directly to the numerical variables.
data df1;
a = .; b=1; c=1; output;
a = 1; b=.z; c=1; output;
a = 1; b=1; c=.; output;
run;
proc format;
value num2char
low-high =[f16.]
other ='NA'
;
run;
/* if only for display purposes */
proc print data=df1;
format a b c num2char.;
run;
/* if storing recoded value in character vars */
data want;
set df1;
array _invars{3} a b c;
array _inval_{3} $16;
do i=1 to dim(_invars);
_inval_[i]=put(_invars[i],num2char.);
end;
run;
proc print data=want;
run;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.
Ready to level-up your skills? Choose your own adventure.