hello all
I have the following data set and I'm trying to switch it's value using proc format but it is not working as expected
data mysurvay1;
input q1 $ q2 $ q3 $;
DATALINES;
1_strogly_agree 4_not_important 3_very_low
1_strogly_agree 3_somewhat_importatnt 9_left_blank
2_agree 9_left_blank 9_left_blank
4_disagree 2_important normal
9_left_blank 2_important 1_high
agree 3_somewhat_importatnt 2_normal
;
run;
proc format;
invalue $qanswer
"1_high" =1
"1_strogly_agree" =1
"2_agree" =2
"2_important" =2
"2_normal" =2
"3_somewhat_importatnt"=3
"3_very_low" =3
"4_disagree" =4
"4_not_important" =4
"9_left_blank" = .
other =999
;
run;
proc print data=mysurvay1;
format q1-q3 $qanswer.;
run;
expected output
q1 | q2 | q3 |
1 | 4 | 3 |
1 | 3 | . |
2 | . | . |
4 | 2 | 999 |
. | 2 | 1 |
999 | 3 | 2 |
but what I'm getting is
may you help me with that
You need to define the INFORMAT before you use it.
If you want the INFORMAT to create a NUMERIC result it needs to be defined as a NUMERIC informat.
proc format;
invalue qanswer
"1_high" =1
"1_strogly_agree" =1
"2_agree" =2
"2_important" =2
"2_normal" =2
"3_somewhat_importatnt"=3
"3_very_low" =3
"4_disagree" =4
"4_not_important" =4
"9_left_blank" = .
other =999
;
run;
Now that you have the informat defined you can use it to read in text and convert them into numbers. (Just like the 5. informat reads in 5 character digit strings and converts them into numbers).
If you already have the Q1 variables defined as character then make new numeric variables.
data mysurvey1;
input (q1-q3) (:$50.);
DATALINES;
1_strogly_agree 4_not_important 3_very_low
1_strogly_agree 3_somewhat_importatnt 9_left_blank
2_agree 9_left_blank 9_left_blank
4_disagree 2_important normal
9_left_blank 2_important 1_high
agree 3_somewhat_importatnt 2_normal
;
data want;
set mysurvey1;
num1 = input(q1,qanswer.);
num2 = input(q2,qanswer.);
num3 = input(q3,qanswer.);
run;
Or just read them in using the INFORMAT so they are defined as numeric to begin with (you will lose the distinction between the various invalid responses).
data mysurvey1;
input (q1-q3) (:qanswer.);
DATALINES;
1_strogly_agree 4_not_important 3_very_low
1_strogly_agree 3_somewhat_importatnt 9_left_blank
2_agree 9_left_blank 9_left_blank
4_disagree 2_important normal
9_left_blank 2_important 1_high
agree 3_somewhat_importatnt 2_normal
;
You create the numeric informat qanswer, but you try to use the character format (note the missing "in") $qanswer.
I have just tired to replace invalue with value in the proc format step. yet I'm still getting the same answer.
I also tried to replace the format with informat in the proc print step but now I'm seeing my original data.
is that what you meant?
You need to define the INFORMAT before you use it.
If you want the INFORMAT to create a NUMERIC result it needs to be defined as a NUMERIC informat.
proc format;
invalue qanswer
"1_high" =1
"1_strogly_agree" =1
"2_agree" =2
"2_important" =2
"2_normal" =2
"3_somewhat_importatnt"=3
"3_very_low" =3
"4_disagree" =4
"4_not_important" =4
"9_left_blank" = .
other =999
;
run;
Now that you have the informat defined you can use it to read in text and convert them into numbers. (Just like the 5. informat reads in 5 character digit strings and converts them into numbers).
If you already have the Q1 variables defined as character then make new numeric variables.
data mysurvey1;
input (q1-q3) (:$50.);
DATALINES;
1_strogly_agree 4_not_important 3_very_low
1_strogly_agree 3_somewhat_importatnt 9_left_blank
2_agree 9_left_blank 9_left_blank
4_disagree 2_important normal
9_left_blank 2_important 1_high
agree 3_somewhat_importatnt 2_normal
;
data want;
set mysurvey1;
num1 = input(q1,qanswer.);
num2 = input(q2,qanswer.);
num3 = input(q3,qanswer.);
run;
Or just read them in using the INFORMAT so they are defined as numeric to begin with (you will lose the distinction between the various invalid responses).
data mysurvey1;
input (q1-q3) (:qanswer.);
DATALINES;
1_strogly_agree 4_not_important 3_very_low
1_strogly_agree 3_somewhat_importatnt 9_left_blank
2_agree 9_left_blank 9_left_blank
4_disagree 2_important normal
9_left_blank 2_important 1_high
agree 3_somewhat_importatnt 2_normal
;
Thank you Tom
That is helpful. may you help me on how to read it the data using the informat like on a data that was already defined (has set statement instead of input).
I tired the code
data mysurvey2;
set mysurvey1;
format q1-q3 qanswer.;
run;
data mysurvey2;
set mysurvey1;
array _q(*) q1-q3;
array _new(*) new_q1-new_q3;
do i=1 to dim(_q);
_new(i) = input(substr(_q(i), 1, 1), 8.);
end;
run;
proc print data=mysurvey2;
var new_q1-new_q3;
run;
proc print data=mysurvey1;
var q1-q3;
format q1-q3 $1.;
run;
Try both of the above options.
thank you Reeza,
may you explain the $1. below what is that ?
proc print data=mysurvey1;
var q1-q3;
format q1-q3 $1.;
run;
@Abdulla1 wrote:
Thank you Tom
That is helpful. may you help me on how to read it the data using the informat like on a data that was already defined (has set statement instead of input).
I tired the code
data mysurvey2;
set mysurvey1;
format q1-q3 qanswer.;
run;
That is something completely different.
INFORMATs are used to convert text into value. A numeric informat (like in my previous answer) converts text into numbers. A character informat converts text into text (character strings).
FORMATs are used to convert values into text. A numeric format, like the qanswer format in your code here, converts numbers into text. A character format converts character string (text) into text.
So for this code to work the variables Q1 to Q4 would need to be numeric. And you would have needed to have define a numeric format that converts values like 1 or 2 into strings. Something like:
proc format ;
value qanswer
1='1_something_or_other'
2='2_another_answer'
...
999='Invalid answer'
.='9_no_response'
;
run;
that explains it all.
thank you very much.😀😀😀
This line is defining Q1 to Q4 to each be character with a length of only 8 bytes.
input q1 $ q2 $ q3 $;
If you only read in 8 of the characters then most of the strings will not match the strings in the format(informat?) definition.
4_not_important
is not the same as
4_not_im
lol they are not in the actual data for sure. but thanks for notifying me.
If you want to just convert the first digit into a number then why not just do that?
data test;
string='4_not_important';
number = input(string,??1.);
if number=. then number=999;
if number=9 then number=.;
run;
that is probably the easiest way of doing it, but it will be harder for me to adjusting some of the values, such as "normal" which doesn't have a number before it and I would code it later as 2.
thanks for the suggestion
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
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.