Dear All
Suppose I have data:
001F36175180
Variable description for this data is:
ID: columns1-3
Sex: columns 4
Age: columns 5-6
Height: columns 7-9
Weight: columns 10-12
I know I can read in this data using code:
input
@1 ID $3.
@4 Sex $1.
@5 Age 2.
@7 Height 3.
@10 Weight 3.;
However, the above method is to read data from left to right; my question is, is there a way to read data from right to left, such as:
input
@12 Weight -3.
@9 Height -3..
@6 Age -2.
@4 Sex -1.
@3 ID -3.;
Why not? As long as you use the correct starting positions and formats. e.g.:
data have;
input
@10 Weight 3.
@7 Height 3.
@5 Age 2.
@4 Sex $1.
@1 ID $3.;
cards;
001F36175180
;
Art
But isn't that still left to right within the fields. I think "
littlestone" is implying with minus sign in front of informat that the field should be right to left not just the record. The only thing I can think of is to reverse the value of _INFILE_ but that is a bit awkward.1799 infile cards;
1800 input @;
1801 _infile_ = reverse(_infile_);
1802 input Weight 69-71;
1803 put weight=;
1804 list;
1805 cards;
Weight=81
RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
1806 08157163F100
NOTE: The data set WORK.HAVE has 1 observations and 1 variables.
DN, Of course you might be correct but, if so, what about the reverse informat? Art
You can use Column Input to read from right to left.
DATA DSN;
INPUT WEIGHT 10-12 HEIGHT 7-9 AGE 5-6 SEX $ 4-4 ID 1-3;
DATALINES;
001F36175180
;
RUN;
PROC PRINT DATA = DSN;
RUN;
Thanks
Dhanasekaran R
thank you all.
I am asking this question because I have a dataset that needs to be read CONDITIONALLY. It seems to me that the data will be easier to manipultae if read from right to left, but, just as data_null_ said, the code looks kind of awkward. I am just wondering if there is some "nicer looking" code can do the job.
Again, thanks a lot.
Hi Littlestone. Are you trying to read the data conditionally, based upon a value in a specific field ? Or is the data in reverse order in the flat file?
If you are trying to read the data based upon a field within the data, such as length then use the @@ to "pause" reading the file.
data results;
input
@1 ID $3.
@4 Sex $1.
@5 Age 2.
@@ ;
if age < 10 then do;
input ; * no height or weight for children under 10;
end;
else do;
input
@7 Height 3.
@10 Weight 3.;
end;
cards;
001F36175180
001F01
;
run;
Otherwise,,
just read in the whole line and use the reverse function;
Cheers.
Thank you very much, Kevin, your answer is very close to what I am looking for.
Actually, part of my problem is that the length of variable Age is not constant (all other variables has defined length). Suppose I have following data:
001F36175180
002F9120100
003F110180160
The age for the above three observations are 36, 9 and 110, respectively. Because of different length of Age (2, 1 and 3, in this example), the starting column for the next variable Height keeps changing, making it difficult to determine where to start reading Height if data has to be read from left to right.
If you can determine the length of the record and subtract the lenght of the know fields then the rest is...
filename FT15F001 temp;
data test;
infile FT15F001 length=l;
input id $3. sex $1. @;
w = l-(3+1+(2*3)); *minus know field widths;
select(w);
when(1) input age 1. @;
when(2) input age 2. @;
when(3) input age 3. @;
end;
input (height weight) (3.);
parmcards;
001F36175180
002F9120100
003F110180160
;;;;
run;
proc print;
run;
or, similarly:
data have;
input
@1 ID $3.
@4 Sex $1.;
;
_infile_=strip(reverse(_infile_));
weight=input(reverse(substr(_infile_,1,3)),3.);
height=input(reverse(substr(_infile_,4,3)),3.);
age=input(substr(reverse(_infile_),5,
length(_infile_)-10),3.);
cards;
001F36175180
002F9120100
003F110180160
;
run;
Instead of the Select statement, just read age using the $varying informat.
input id $3. sex $1. @;
w = l-(3+1+(2*3)); *minus know field widths;
input age $varying. w (height weight) (3.);
Of course, for l, you mean length(_infile_), but very nice solution!
SAS_Bigot wrote:
Instead of the Select statement, just read age using the $varying informat.
input id $3. sex $1. @;
w = l-(3+1+(2*3)); *minus know field widths;
input age $varying. w (height weight) (3.);
I think age should be numeric. So you will need to read it again with INPUT function. Six of one, half dozen of the other.
Thank you all. I really learned a lot.
Good that you learned. The person who prepared the file also has things to learn. The design is very bad. Were there two variable-length fields instead of one, it would have been difficult if not impossible to parse.
littlestone wrote:
Thank you all. I really learned a lot.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.
Find more tutorials on the SAS Users YouTube channel.