I keep on getting errors in SAS - sas

I am just testing my SAS code it was working but now it is not. It says it is invalid.
Sample code:
data have;
$ default $ student $;
cards;
(1) yes yes
(2) Yes No
(3) NO Yes
(4) No No
;
Thanks in advance!

I suspect you wanted to have an INPUT statement in your code. Also you need to have a variable name for that first string.
data have;
input col1 $ default $ student $;
cards;
(1) yes yes
(2) Yes No
(3) NO Yes
(4) No No
;

Related

change a length format of a column in sas

This is my code:
data want ;
input branch_id branch_name $ branch_specification $ bold_type $ bold_score $ ;
DATALINES ;
612 NATANYA masham_atirey masham 1.15
;
run ;
the output for branch_specification is masham_a
I wish to longer the lenght.
You could add a length statement under your data statement.
length branch_specification $15.;
Just keep in mind that the length statement will put your manipulated variable at the front of your data set. You can change the order with a retain statement.
data want ;
retain branch_id branch_name branch_specification;
length branch_specification $15.;
input branch_id branch_name $ branch_specification $ bold_type $ bold_score $ ;
DATALINES ;
612 NATANYA masham_atirey masham 1.15
;
run ;
You can input branch_specification using the $15. informat while using list input for the rest, e.g.
data want ;
input branch_id branch_name $ branch_specification :$15. bold_type $ bold_score $ ;
DATALINES ;
612 NATANYA masham_atirey masham 1.15
;
run ;
This way you don't need a separate length statement, and the variable order is unchanged.
Adding the : modifier prevents the input statement reading past the first delimiter (space by default) into the next variable in cases where branch_specification is less than 15 characters long.

Changing a SAS character variable into a SAS numerical variable?

I have created the following SAS table:
DATA test;
INPUT name$ Group_Number;
CARDS;
Joseph 1
Stephanie 2
Linda 3
James 1
Jane 2;
run;
I would like to change group number from a character type into a numeric type.
Here is my attempt:
data test2;
set test;
Group_Number1 = input(Group_Number, best5.);
run;
The problem is that when I execute:
proc contents data = test2;
run;
The output table shows that group number is still of a character type. I think that the problem may be that I have "best5." in my input statement. However I am not 100% sure what is wrong.
How can I fix the solution?
If you have a character variable your code will work. But you don't, you have a numeric variable in your sample data. So either your fake data is incorrect, or you don't have the problem you think you do.
Here's an example that you can run to see this.
*read group_number as numeric;
DATA test_num;
INPUT name$ Group_Number;
CARDS;
Joseph 1
Stephanie 2
Linda 3
James 1
Jane 2
;
run;
Title 'Group_Number is Numeric!';
proc contents data=test;
run;
*read group_number as character;
DATA test_char;
INPUT name$ Group_Number $;
CARDS;
Joseph 1
Stephanie 2
Linda 3
James 1
Jane 2
;
run;
data test_converted;
set test_char;
group_number_num = input(group_number, 8.);
run;
Title 'Group_Number is Character, Group_Number1 is Numeric';
proc contents data=test_converted;
run;
try this:
data test2;
set test;
Group_Number1 = input(put(Group_Number,best5.),best5.);
run;

Using Arrays for loops in SAS

I have this dataset
DATA Problem3;
INPUT name $ Smoke_Tobacco $ Drink_Alcohol $ Take_Illegal_Drugs $ Drink_Soda $;
DATALINES;
Tom yes no no yes
Harry Yes Yes Yes No
Jim No No No Yes
Bob Yes No No Yes
Andy No Yes No Yes
Cody yes no no no
Ed Yes no no yes
Greg no Yes no No
Dave Yes No Yes no
;
RUN;
And I want to use loops to change all "yes" responses to "Yes" and all "no" responses to "No".
My idea is to use arrays for this such as what is shown in the Little SAS workbook
DATA songs;
INFILE 'c:\MyRawData\KBRK.dat';
INPUT City $ 1-15 Age wj kt tr filp ttr;
ARRAY song (5) wj kt tr filp ttr;
DO i = 1 TO 5;
IF song(i) = 9 THEN song(i) = .;
END;
Run;
Which replaces "9" with ".". So I edit my code to
DATA Problem3;
INPUT name $ Smoke_Tobacco $ Drink_Alcohol $ Take_Illegal_Drugs $ Drink_Soda $;
DATALINES;
Tom yes no no yes
Harry Yes Yes Yes No
Jim No No No Yes
Bob Yes No No Yes
Andy No Yes No Yes
Cody yes no no no
Ed Yes no no yes
Greg no Yes no No
Dave Yes No Yes no
;
ARRAY Answer (4) Smoke_Tobacco Drink_Alcohol Take_Illegal_Drugs Drink_Soda;
DO i=1 TO 9;
IF Answer(i) = 'yes' THEN Answer(i)= 'Yes';
ELSE IF Answer(i) = 'no' THEN Answer(i)= 'No';
END;
RUN;
But I get errors saying that the lines in my addition are either not valid or out of order. How do I go about fixing this?
Declare your array as a character, so add the $ into the array declaration
Just apply PROPCASE to the variables which will standardize all to have the first letter as a capital.
Why are you looping to 9, when you only have 4 items?
You have to put the array statements BEFORE the datalines. Nothing after the data is processed.
DATA Problem3;
INPUT name $ Smoke_Tobacco $ Drink_Alcohol $ Take_Illegal_Drugs $ Drink_Soda $;
ARRAY Answer (4) $3. Smoke_Tobacco Drink_Alcohol Take_Illegal_Drugs Drink_Soda;
DO i=1 TO 4;
answer(i)=propcase(answer(i));
END;
DATALINES;
Tom yes no no yes
Harry Yes Yes Yes No
Jim No No No Yes
Bob Yes No No Yes
Andy No Yes No Yes
Cody yes no no no
Ed Yes no no yes
Greg no Yes no No
Dave Yes No Yes no
;
RUN;
You cannot add statements after the end of the data step!
Just move your new statement to before the DATALINES; statement that marks the end of your data step and the beginning of your in-line data. Also make sure the upper bound on your do loop matches the size of your array. Let SAS figure that out for you. do i=1 TO dim(answer);
This is the second confusion along these lines that I have seen recently? I wonder if it is caused by people reflexively adding an extra run; statement after the end of their data steps that use in-line data? That extra run; is not needed and becomes a new empty step, not part of the original data step.

SAS lowercase SHA256 string

Currently testing a SHA256 function in order to prepare a variable for use in another application.
The user has requested the SHA256 result be in lower case. I created a quick record in order to make sure I can convert the string-
data have;
input first $ last $ dob $ 10. sex $;
cards;
test person 1955-07-31 1
;
run;
Seems it will not allow a lower case string once passed through the SHA function.
Is there a workaround for this? The below attempt did not yield desirable results.
data have2;
set have;
source = catt(first,last,dob,sex);
encryp = lowcase(sha256(source));
format encryp $hex64.;
run;
The issue is not with the sha256 function, but with the $HEX64 format.
When you used lowcase you actually do some harm to the SHA256 result: you're not altering the hexadecimal representation, but you're actually altering the characters themselves, which means your result isn't accurate - and then you're displaying them with $HEX64. which will always show capital letters for the hexadecimal characters.
What instead you want, presumably, is to store the lower case version of the $HEX64. format. You can do that with put:
data want;
set have;
source = catt(first,last,dob,sex);
encryp = sha256(source);
lower = lowcase(put(encryp,$HEX64.));
run;
Note what encryp looks like - something totally different, and probably not particularly useful. You can of course skip that step if you want.
Below will do it using a put statement with the format inside:
data have2;
set have;
encryp = lowcase(put(sha256(catt(first,last,dob,sex)),$hex64.));
run;
It will show an entirely different encryption code compared to your method but it remains consistent.
data have;
input first $ last $ dob $ 10. sex $;
cards;
test person 1955-07-31 1
test person 1955-07-31 1
test2 person 1977-08-11 2
test3 person 1945-12-22 1
;
run;
data have2;
set have;
new_encryp = lowcase(put(sha256(catt(first,last,dob,sex)),hex64.)); /* new method */
encryp = lowcase(sha256(catt(first,last,dob,sex))); /* what you tried */
format encryp $hex64.;
run;
/* output */
first last dob sex new_encryp encryp
test person 7/31/1955 1 038a855a47f40edf54094adc4366e3e79c1a931346d7968e96d2cb930b01e7bc 039A857A67F40EDF74096AFC6366E3E79C1A931366D7969E96F2EB930B01E7BC
test person 7/31/1955 1 038a855a47f40edf54094adc4366e3e79c1a931346d7968e96d2cb930b01e7bc 039A857A67F40EDF74096AFC6366E3E79C1A931366D7969E96F2EB930B01E7BC
test2 person 8/11/1977 2 1117ab614f48a7edfbe9d615f12acad9d564b457b0f31bb2619f7eb9b10f1e58 1117AB616F68A7EDFBE9F615F12AEAF9F564B477B0F31BB261FF7EB9B10F1E78
test3 person 12/22/1945 1 d1cb00ebe044c0553039f99592dc7bd4804eac2c13da8208fd82459c3a37efd1 F1EB00EBE064E0753039F99592FC7BF4806EAC2C13FA8208FD82659C3A37EFF1
*convert case;
%let txt="SEQ_CLAIM_ID, SEQ_MEMB_ID, EFFECTIVE_DATE";
%macro lower_case(txt);
data;
text=lowcase(&txt);
run;
%mend;
%lower_case(&txt);

Embed SAS Macro Results in SAS code

I would like to include the results of a macro function call in a data step. I can do this indirectly, by first assigning the macro function output to a macro variable, and then using that macro variable within my function, but this seems inelegant.
data dataset_employee;
input name $ dept $;
datalines;
John Sales
Mary Acctng
;
data dataset_employee;
input name $ dept $;
datalines;
John Sales
Mary Acctng
;
data dataset_manager;
input name $ dept $;
datalines;
Will Sales
Sue Acctng
;
It seems like SAS doesn't realize that the macro call is complete and I'm switching to regular SAS code.
/*this works*/
%let var = %DO_OVER(VALUES=employee, PHRASE=dataset_?) dataset_manager;
data combined1;
set &var dataset_manager;
run;
/*this fails*/
data combined;
set %DO_OVER(VALUES=employee manager, PHRASE=dataset_?);
dataset_manager;
run;
/*this works*/
data combined;
set dataset_manager %DO_OVER(VALUES=employee manager, PHRASE=dataset_?);
;
run;
Can anyone help me understand what is going on here?
It seems that the failing attempt is due to an extra ; at the end of the macro invocation. Try removing it.
A macro call doesn't require a semicolon.
The first example works without a semicolon after the macro call (pay attention, you are using the dataset_manager dataset twice, in the %let and again in the set statement).
The third example would work even if you remove one of the two semicolons (one is required to end the set statement).