data _NULL_ (drop=TeamName);
length Event3 Event2 Event1 8. TeamName ParticipantName $8. ;
format Event2 z8. ;
retain TeamName Count ;
input TeamName $ Count @ ;
do i = 1 to Count ;
input ParticipantName $ Event1 Event2 Event3 @@ ;
TeamTotal + (Event1 + Event2 + Event3);
output ;
FILE 'C:\Users\user\Desktop\IDS SAS 594\samplefile.txt' ;
if _N_=3 then do ;
if i = 1 then do ;
put TeamName Count @@ ;
end ;
if i < 2 then do ;
put ParticipantName Event1 Event2 Event3 @@ ;
end ;
else do ;
put ParticipantName Event1 Event2 Event3 ;
end ;
end ;
else do ;
put TeamName Count ;
put ParticipantName Event1 Event2 Event3 ;
end ;
end ;
datalines;
Knights 1
Sue 6 8 8
Kings 1
Jane 9 7 8
Knights 4 John 7 7 7 Lisa 8 9 9
Fran 7 6 6
Walter 9 8 10
;
I do not understand the bold parts.
Help
Next, look at these pieces of code:
do i = 1 to Count;
.......
if _N_ = 3 then do;
if i = 1 then do;
put TeamName Count @@;
end;
if i < 2 then do;
One can easily see that the variable i will only have ordinal values of 1,2,3,.....
Therefore the condition i < 2 is equivalent to i = 1, and the two blocks can be merged into one with the same functionality, which would also improve readability.
Retain creates and identifies a variable whose values are kept from one observation (record) to the next.
_N_ is an automatic variable that SAS supplies to identify the record .
So if _N_=3 then do is "When this is the third record do something"
You have a group of statements done for values of 1 to the value of count on the current record that starts with : do i = 1 to Count ; to the END; just before datalines.
if i < 2 then do ; If Count is 2 or larger then the loop will increment and the counter variable i, when the counter is less than 2 point it prints the values of some variables to the log.
Since i will have values like 1 , 2 ,3 the same effect could be done with i=1 to print on the first pass through the loop.
Concerning "if _N_ = 3 do"
But I thought that SAS Data step updates _N_ after the iteration.
Meaning when the data step iterates to the 3rd recound, _N_ is still equal to 2. Only after finishing the 3rd record do _N_ gets updated to 3?
Actually, the interpretation of _N_ is a bit tricky here: It counts the iterations of the data step. In many cases this coincides with the "record number," as @ballardw pointed out. In the present data step, however,
(See documentation on "Automatic Variables.")
Just for completeness: The single trailing @ at the end of the first INPUT statament "holds an input record for the execution of the next INPUT statement within the same iteration of the DATA step" (INPUT statement documentation). This is relevant here when the fifth data line is being read. After reading "Knights 4" the pointer must stay on the same input record to let the next INPUT statement read "John" etc. and not "Fran" (ignoring the rest of the previous line).
All posters:
Look thoroughly at that data step, it reads from DATALINES and writes to the file in the FILE statement. What is especially puzzling is that a keep/drop option is used on _NULL_ and a completely useless OUTPUT statement is present.
First, put some proper formatting into this horrible piece of spaghetti code:
data test /*(drop=TeamName)*/;
file '$HOME/sascommunity/samplefile.txt' ;
length Event3 Event2 Event1 8. TeamName ParticipantName $8.;
format Event2 z8.;
retain TeamName Count;
input TeamName $ Count @;
do i = 1 to Count;
input ParticipantName $ Event1 Event2 Event3 @@;
TeamTotal + (Event1 + Event2 + Event3);
output;
if _N_ = 3 then do;
if i = 1 then do;
put TeamName Count @@;
end;
if i < 2 then do;
put ParticipantName Event1 Event2 Event3 @@;
end ;
else do ;
put ParticipantName Event1 Event2 Event3;
end;
end;
else do;
put TeamName Count;
put ParticipantName Event1 Event2 Event3;
end;
end;
datalines;
Knights 1
Sue 6 8 8
Kings 1
Jane 9 7 8
Knights 4 John 7 7 7 Lisa 8 9 9
Fran 7 6 6
Walter 9 8 10
;
run;
Now it becomes easier to see that the if _N_ = 3 block is only there to recreate the layout of the datalines in the output file (more or less, as event2 now has a z8. format).
Does this have ANY practical use?
No, this piece of code is written by my professor for demonstration purposes. It has no practical use. It is there to show us how to use a double trailing @@ to input the datalines as shown.
Next, look at these pieces of code:
do i = 1 to Count;
.......
if _N_ = 3 then do;
if i = 1 then do;
put TeamName Count @@;
end;
if i < 2 then do;
One can easily see that the variable i will only have ordinal values of 1,2,3,.....
Therefore the condition i < 2 is equivalent to i = 1, and the two blocks can be merged into one with the same functionality, which would also improve readability.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.