Creating a flag for first and last in SAS - if-statement

I want to be able to create a flag, here called timeflag, that is set to 1 for every first and last entry of a certain Session, designated by logflag. What I have is the following but this gives me null data points:
data OUT.TENMAY_TIMEFLAG;
set IN.TENMAY_LOGFLAG;
if first.logflag then timeflag = 1;
if last.logflag then timeflag = 1;
run;
What is it about the first. and last. functions that I am not understanding here or is it that I have 2 if statements?

To have SAS create FIRST. and LAST. automatic variables you need to use a BY statement. If you want the new variable to be coded 1/0 then no need for the IF statement, just assign the automatic variable to a new permanent variable. To make one variable that is 1 for the first and the last then just use an OR.
data want;
set have;
by logflag ;
timeflag = first.logflag or last.logflag ;
run;

data OUT.TENMAY_TIMEFLAG;
set IN.TENMAY_LOGFLAG;
by logflag;
if first.logflag then timeflag = 1;
if last.logflag then timeflag = 1;
run;
P.S. in this case the dataset IN.TENMAY_LOGFLAG should be sorted by logflag.

Related

SAS- How Code an array from previous set of variables

I need to create a new variable in which is comprised of a list of other variables found in my dataset.
HAD1 (1=yes 2=no 9=unknown),
HAF10 (1=yes 2=no 9=unknown),
HAC1C (1=yes 2=no 9=unknown),
and HAC1D (1=yes 2=no 9=unknown)
to add up the number of health conditions an individual has. I also want to set all 9 to equal "."
My new variable will be named CC4
CC4 =
(0=no conditions,
1=one condition,
2=two conditions,
3=three conditions,
4=four conditions,
.=any condition appears missing)
How do I code it in the correct way and add it to my dataset?
I only wrote this:
data dataset;
set dataset;
*use arrays to create clean, re-coded versions of variables;
array code1 [4] HAD1 HAF10 HAC1C HAC1D;
array code2 [4] diabetes hattack hfailure stroke;
do new= 1 to 4;
if code1 [new] = 1 then code2 [new] = 1;
*keep all 1's as 1's;
else if code1 [new] = 2 then code2 [new] = 2;
*keep all 2's as 2's;
else if code1 [new] = 9 then code2 [new] = .;
*make all 9's into .'s;
end;
drop new;
*create summation variable;
cc4=HAD1+HAF10+HAC1C+HAC1D;
You don't need to recode to count.
You can take advantage of SAS evaluating boolean expressions to 1 for TRUE and 0 for FALSE.
data want;
set have;
cc4 = (HAD1=1)+(HAF10=1)+(HAC1C=1)+(HAC1D=1);
run;
PS Do not overwrite your input data by using the same dataset name in the DATA and SET statements. It will make it hard to correct coding mistakes.
If you want new names for the original code variables, use RENAME
If you want new names and the original code variables, probably shouldn't
If you only want the cc4 result, you can use the fact of a single digit code for meaning to compute your condition count when all conditions assert a yes/no state.
Example:
data have;
do code1 = 1,2,9;
do code2 = 1,2,9;
do code3 = 1,2,9;
do code4 = 1,2,9;
output;
end;end;end;end;
run;
data want;
set have;
codes = cats(code1,code2,code3,code4);
drop codes;
cc4 = ifn(index(codes,'9'),.,count(codes,'1'));
run;
In your case replace code1,code2,code3,code4 with HAD1,HAF10,HAC1C,HAC1D

SAS Data Step / Pointer / Indirect Variable Assignment

In a SAS Data Step i have a character variable called "varName". This variable stores the name of another variable. In below's example, it stores the name of the numeric variable "changeMe":
data TMP;
length
varName $32
changeMe 8
;
varName = ‘changeMe’;
/*??? How to change the content of variable that varName holds ???*/
run;
Now the question is: how do i change the content of the variable that varName holds?
The use case would be that varName acts as a dynamic pointer to different variables that i want to manipulate in a big SAS Data Set.
DATA Step does not directly provide for named indirect assignment.
In some cases, the indirect assignment requirement might indicate you want to perform a Proc TRANSPOSE data transformation. If the variable names and values are provided in a transaction data set, and the data has BY group variables, your better solution might be to TRANSPOSE the transaction data and merge that transform to the master data using an UPDATE or MODIFY statement.
Regardless, you can array variables of a given type and iterate the array looking for the target requiring assignment.
Example:
data want;
set sashelp.class;
varname = 'name';
varvalue = 'Scooter';
array chars _character_;
do _n_ = 1 to dim(chars);
if upcase (vname(chars(_n_))) = upcase(varname) then do;
chars(_n_) = varvalue;
end;
end;
run;
Output
call execute() is a highly feasible solution.
data TMP;
length
varName $32
changeMe 8
;
varName = 'changeMe';
run;
data _null_;
set TMP end=eof;
if _n_ = 1 then call execute('data %trim(&syslast.); modify %trim(&syslast.);');
call execute(cats(varName)||' = rand("uniform",1,0);');
if eof then call execute('run;');
run;
Log:
NOTE: CALL EXECUTE generated line.
1 + data WORK.TMP; modify WORK.TMP;
2 + changeMe = rand("uniform",1,0);
3 + run;
NOTE: There were 1 observations read from the data set WORK.TMP.
NOTE: The data set WORK.TMP has been updated. There were 1 observations rewritten, 0 observations
added and 0 observations deleted.

putting data into character variable sas

I'm facing the problem that I want to put data into a character variable.
So I have a long tranposed dataset where I have three variables: date( by which i transposed before hand) var (has three different outputs of my previous variables) and col1 (which includes the values of my previous variables).
Now i want to create a forth variable which has as well three different outputs. My problem is that I can create the variable put with my code it does always create missing value.
data pair2;
set data1;
if var="BNNESR" or var="BNNESR_r" or var="BNNESR_t" then output;
length all $ 20;
all=" ";
if var="BNNESR" then all="pdev";
if var="BNNESR_t" then all="trigger";
if var="BNNESR_r" then all="rdev";
drop var;
run;
Afterwards I want to tranpose it back by the "all" variable. I know i could just rename the old vars before I transpose it and then just keep them.
But the complete calculation will go on and actually will be turned into a macro where it is not that easy if would do it like that way.
Your program will just subset the input data and add a new variable that is empty because you are writing the data out before you assign any value to the new variable.
Use a subsetting IF (or WHERE) statement instead of using an explicit OUTPUT statement. Once your data step has an explicit OUTPUT statement then SAS no longer automatically writes the observation at the end of the data step iteration.
data pair2;
set data1;
if var="BNNESR" or var="BNNESR_r" or var="BNNESR_t" ;
length all $20;
if var="BNNESR" then all="pdev";
else if var="BNNESR_t" then all="trigger";
else if var="BNNESR_r" then all="rdev";
drop var;
run;
Since the list in the IF statement matches the values in the recode step then perhaps you want to just use a DELETE statement instead?
data pair2;
set data1;
length all $20;
if var="BNNESR" then all="pdev";
else if var="BNNESR_t" then all="trigger";
else if var="BNNESR_r" then all="rdev";
else delete;
drop var;
run;

SAS: Add Conditional Variable To Existing Data Source

First time writing SAS code. Trying to add a new numeric variable that has a conditional value based on another existing variable. This is what I have so far:
data dataset;
set dataset;
newnum = .;
If oldnum >= 2;
newnum = 1;
run;
I'm getting an error when I try to run this SAS Code node that is attached to the relevant data source item.
There is no conditional statement in your code because you end your IF block with a semicolon. You need to move the newnum up to before the semicolon and add a THEN.
data dataset;
set dataset;
newnum = .;
If oldnum >= 2 then newnum = 1;
run;
As is, the line If oldnum >=2 will filter your dataset and keep only records that have oldnum>=2. Then it will assign newnum=1. So it does do what you want, but the resulting dataset will only be a subset of the original data set.

How to iterate simoultaneusly throught two sets in SAS?

I've tried something like this :
data wynik;
set dane;
if x>3 than x3=3*x;
else set dane2; x3=x2;set dane;
run;
dane and dane2 have the same number of rows
result is interesting - condition x>3 is still holding after setting dane2, but SAS always takes first observation - that is, it doesn't pass the current state of hidden loop counter. Make question is - does SAS have/use hidden loop with counter while iterating through dataset which could be accessed by user ?
editon :
mayby I should add in title - without expicit loops, but this would also be welcomed
Making some assumptions:
data dane;
do x = 1 to 5;
output;
end;
run;
data dane2;
do x2 = 5 to 1 by -1;
output;
end;
run;
data wynik;
merge dane dane2;
if x > 3 then x3=3*x;
else x3=x2;
put x3=;
run;
That uses the side-by-side merge (merge with no by statement) to get you both values at once.
To answer your followup question:
does SAS have/use hidden loop with counter while iterating through dataset which could be accessed by user ?
Yes, it does; _n_ defines the current loop iteration (as long as it isn't modified externally, which it can be - it is just a regular variable that's not written out to the dataset). So you could similarly do the following:
data wynik;
set dane;
if x > 3 then x3=x*3;
else do;
set dane2 point=_n_;
x3=x2;
end;
put x3=;
run;
The side-by-side merge is preferred because it will be faster, unless you very infrequently need to look at DANE2. It's also easier to code.