Globally set length for all string variable in SAS - sas

Is there a global option to override the default length options for string in SAS? The only way that I have found is by setting the length statement within a data or proc step. This is not ideal for me as I would need to rework a large amount of code.

Related

How do I format new variables that I Create?

I am trying to create a new variable in SAS. I use if then logic to create a new character variable. However, the variable is being truncated. How do I format the new variable so that all the characters appear?
DATA Clinic;
set stat201.clinic;
rename age_at_consent=Age ldiastolic=dbp lsystolic=sbp ldobp=datebp;
if smoking="" then smoking="Missing";
if smokecat=0 then smokecat_1="Never Smoker";
if smokecat=1 then smokecat_1="Current Everyday Smoker";
if smokecat=2 then smokecat_1="Former Smoker";
if smokecat=9 then smokecat_1="Never Assessed";
attrib smokecat_1 format =$25.;
drop smokecat;
rename smokecat_1= smokecat;
run;
SAS will define the variable based on when it first appears. Since the first appearance is in this assignment statement.
if smokecat=0 then smokecat_1="Never Smoker";
It will be defined as a character variable of length 12.
Just define the variable BEFORE using it. You can use a LENGTH statement
length smokecat_1 $25;
or an ATTRIB statement to define a variable.
attrib smokecat_1 length=$25;
Attaching the $25. format does not change the length of the variable.
It just means that you want SAS to use 25 characters to display the values. But the variable will still only be 12 characters long. There is no need to attach any format to the variable. Formats are instructions on how to display values and SAS already knows how to display character values.
To complement Tom's answer above:
SAS will define the variable type and length based on when it first appears.
I agree it is a good practice to define a variable before using it.

How to use call symput on a specific observation in SAS

I'm trying to convert a SAS dataset column to a list of macro variables but am unsure of how indexing works in this language.
DATA _Null_;
do I = 1 to &num_or;
set CondensedOverrides4 nobs = num_or;
call symputx("Item" !! left(put(I,8.))
,"Rule", "G");
end;
run;
Right now this code creates a list of macro variables Item1,Item2,..ItemN etc. and assigns the entire column called "Rule" to each new variable. My goal is to put the first observation of "Rule" in Item1, the second observation in that column in Item2, etc.
I'm pretty new to SAS and understand you can't brute force logic in the same way as other languages but if there's a way to do this I would appreciate the guidance.
Much easier to create a series of macro variables using PROC SQL's INTO clause. You can save the number of items into a macro variable.
proc sql noprint;
select rule into :Item1-
from CondensedOverrides4
;
%let num_or=&sqlobs;
quit;
If you want to use a data step there is no need for a DO loop. The data step iterates over the inputs automatically. Put the code to save the number of observations into a macro variable BEFORE the set statement in case the input dataset is empty.
data _null_;
if eof then call symputx('num_or',_n_-1);
set CondensedOverrides4 end=eof ;
call symputx(cats('Item',_n_),rule,'g');
run;
SAS does not need loops to access each row, it does it automatically. So your code is really close. Instead of I, use the automatic variable _n_ which can function as a row counter though it's actually a step counter.
DATA _Null_;
set CondensedOverrides4;
call symputx("Item" || put(_n_,8. -l) , Rule, "G");
run;
To be honest though, if you're new to SAS using macro variables to start isn't recommended, there are usually multiple ways to avoid it anyways and I only use it if there's no other choice. It's incredibly powerful, but easy to get wrong and harder to debug.
EDIT: I modified the code to remove the LEFT() function since you can use the -l option on the PUT statement to left align the results directly.
EDIT2: Removing the quotes around RULE since I suspect it's a variable you want to store the value of, not the text string 'RULE'. If you want the macro variables to resolve to a string you would add back the quotes but that seems incorrect based on your question.

explain what is happening in Proc Sql

select Name into :Dataset1-:Dataset%trim(%left(&DatasetNum)) from MEM;
I am not able to interpret what is happening here in this statement can anyone give me an explanation.
I understand this stament
select count(Name) into :DatasetNum from MEM
But not the above one.
It is attempting to use the value of the macro variable DATASETNUM as the upper bound on the macro variable names that are being created by the SELECT statement. Because the previous variable was created with leading spaces the %LEFT() macro is called to remove them. The call to the macro %trim() is not needed as trailing spaces would not cause any trouble.
It is much easier to just build the macro variable array first and then set the counter variable from the value of the automatic macro variable SQLOBS. Plus then it will not have the leading blanks.
select name into :Dataset1- from mem ;
%let DatasetNum=&sqlobs;
If you have an older version of SAS that doesn't support the new :varname- syntax then just use a large value for the upper bound. SAS will only create the number of macro variables it needs.
select name into :Dataset1-:Dataset99999 from mem;
This is creating an array of SAS macro variables (DATASET1, DATASET2, DATASET3) etc, populated from the Name column of the MEM dataset.
It is analagous to:
data _null_;
set MEM;
call symputx(cats('Dataset',_n_),Name);
run;

Is there a reason why array cannot be referenced in a keep= data set options?

The following is the code.
data WORK.TOTALSALES(keep=MonthSales{12});
set WORK.MONTHLYSALES(keep=Year Product Sales);
array MonthSales{12};
do i=1 to 12;
MonthSales{i}=Sales;
end;
drop i;
run;
Many thanks for your time and attention.
The keep= dataset option does not support arrays, but it does support sequentially numbered variables.
data WORK.TOTALSALES(keep=MonthSales1-MonthSales12);
set WORK.MONTHLYSALES(keep=Year Product Sales);
array MonthSales{12};
do i=1 to 12;
MonthSales{i}=Sales;
end;
drop i;
run;
A SAS Array in a Data Step is just a logical grouping of variables. That grouping is only available to the processing inside that data step. Data set options like drop= and keep= are handled by the SAS IO system, which is independent of the Data Step.
A SAS array, as documented in SAS(R) 9.4 Language Reference: Concepts, Fifth Edition has the following restriction:
An array definition is in effect only for the duration of the DATA
step. If you want to use the same array in several DATA steps, you
must redefine the array in each step.
So even if you were to use the drop= (instead of keep=) data set option on WORK.TOTALSALES for some other variables in the data step, the array would still not be part of the output data set as it only exists within the data step that it is defined in with the array statement.

Change variable length in SAS dataset

I need to change the variable length in a existing dataset. I can change the format and informat but not the length. I get an error. The documentation says this is possible but there are no examples.
Here is my issue. My data source could change so I don't want to pre define columns on import. I want to do a generic import and then look for certain columns and adjust the length.
I have tried PROC SQL and DATA steps. It looks like the only way to do this is to recreate the dataset or the column. Which I don't want to do.
Thanks,
Donnie
If you put your LENGTH statement before the SET statement, in a Data step, you can change the length of a variable. Obviously, you will get truncation if you have data longer than your new length.
However, using a DATA step to change the length is also re-creating the data set, so I'm confused by that part of your question.
The only way to change the length of a variable in a datastep is to define it before a source (SET) dataset is read in.
Conversely you can use an alter statement in a proc sql. SAS support alter statement
Length of a variable remains same once you set the dataset. Add length statements before you set the dataset if you need to change length of a columns
data a;
length a, b, c $200 ;
set b ;
run ;