BookmarkSubscribeRSS Feed
MisterJenn
Fluorite | Level 6

I am trying to create a new permanent SAS data set with the following variables. 

data bone;
infile "\\apporto.com\dfs\GWU\Users\kennedyhinnant_gwu\Downloads\Assignment 4\bone.txt";
input @1 dob 1-10. @11 dov 11-20. @21 wt $ 21-26. @27 ht 27-30. @31 peri $ 31-35. 
	  endo $ 35-40 tibia $ 41-44 tanner 45 sex 46;
age = (dov - dob)/365;
logperi = log(peri);
run;
181  data bone;
182  infile "\\apporto.com\dfs\GWU\Users\kennedyhinnant_gwu\Downloads\Assignment 4\bone.txt";
183  input @1 dob 1-10. @11 dov 11-20. @21 wt $ 21-26. @27 ht 27-30. @31 peri $ 31-35.
                    ---            ---
                    22             22
ERROR: Invalid decimal specification.
183  input @1 dob 1-10. @11 dov 11-20. @21 wt $ 21-26. @27 ht 27-30. @31 peri $ 31-35.
                                                   ---
                                                   22
ERROR 22-322: Expecting an integer constant.

ERROR: The ending column position 1 is before the starting column position 11.
ERROR: Invalid decimal specification.
183  input @1 dob 1-10. @11 dov 11-20. @21 wt $ 21-26. @27 ht 27-30. @31 peri $ 31-35.
                                                                 ---
                                                                 22
ERROR 22-322: Expecting an integer constant.

ERROR: The ending column position 1 is before the starting column position 21.
ERROR: Invalid decimal specification.
ERROR: The ending column position 1 is before the starting column position 27.
ERROR: Invalid decimal specification.
183  input @1 dob 1-10. @11 dov 11-20. @21 wt $ 21-26. @27 ht 27-30. @31 peri $ 31-35.
                                                                                   ---
                                                                                   22
ERROR 22-322: Expecting an integer constant.

184        endo $ 35-40 tibia $ 41-44 tanner 45 sex 46;
ERROR: The ending column position 1 is before the starting column position 31.
ERROR: Invalid decimal specification.
185  age = (dov - dob)/365;
186  logperi = log(peri);
187  run;

NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
      186:15
NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.BONE may be incomplete.  When this step was stopped there were 0
         observations and 11 variables.
WARNING: Data set WORK.BONE was not replaced because this step was stopped.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.03 seconds

 

5 REPLIES 5
ballardw
Super User

The variable that receives a value appears on the LEFT of the equal sign.

instead of:

log(peri) = logperi;

use

logperi = log(peri);

 

Patrick
Opal | Level 21

You are using column input which lists the from-to column. This syntax doesn't require a period. 

Patrick_1-1665450449115.png

Column input also doesn't require pointer control @<n> because you're defining the start and end columns already explicitly.

Patrick_2-1665450649816.png

 

Assuming dob is Date of Birth and in your source data you've got something like 20Mar2001, trying to read this string as a number will fail. What you need to do is provide SAS the instruction how to read and convert the source string to a SAS Date value. That's done via an INFORMAT. Using the appropriate informat will read the source string and convert it into a SAS Date value (count of days since 1/1/1960). Applying a FORMAT will then print this count of days in a human readable form as a date.

 

For a blank delimited source file like...

Patrick_3-1665451716930.png

...code as below would work.

data bone;
  infile "c:\temp\bone.txt" dsd dlm=' ' truncover;
  input dob :date9. dov :date9. wt $ 21-26;
  format dob dov date9.;
  age = yrdif(dob,dov,'age');
  logperi = log(peri);
run;

To calculate the age: Use function yrdif() which handles even leap years.

 

Patrick_0-1665452382348.png
If you want to create a permanent SAS data set that doesn't get automatically deleted after your SAS session ends then you need to a) define a libname that points to permanent storages and b) use a two level name with the libref in your data statement <libref>.<table name>

 

And last but not least: Lookup the INFILE statement and what the highlighted parameters below do for you.
Patrick_0-1665452869953.png

 

 

MisterJenn
Fluorite | Level 6
This code only accounts for wt, age variables. The other variables are now missing data
Patrick
Opal | Level 21

@MisterJenn This is a template for you to do some own work.

Tom
Super User Tom
Super User

Are you trying to read the data using column mode input?

If so why did you also include cursor motion commands?  Those are not needed as to start and stop columns are already included.

 

Are you trying to have SAS insert an implied decimal point into your numbers?  If so then you need to include the number of implied decimal places after the period.  If not then why did you include a decimal point after the ending column number? 

 

Is PERI supposed to be a numeric value?  If so then why did you create it as a character variable by including the $ in the INPUT statement?  If not then why are you trying to pass a character string to the LOG() function?

 

Does your source file have the DOV and DOB variables stored as the raw number of days since 1960 ?  If so then why would they need 10 columns in the source text file?  The value that represents today is 22,928 which only needs 5 characters.  And if you have any 120 year olds in your data the value that represents 01JAN1900 is -21,914 which only needs 6 characters including the minus sign.

1247  data _null_;
1248   today=date();
1249   jan1900 = '01JAN1900'd ;
1250   put (_all_) (=comma10./);
1251  run;

today=22,928
jan1900=-21,914

You probably need to use an informat with the DOV and DOB variables.

 

You cannot tell SAS to use an informat when using column mode input.  So you will want switch to a hybrid method that uses column mode for most of the variables and formatted mode to handle the two date values.

 

You don't say how the dates are entered so let's assume the 10 character strings in your text file are in a style that the YYMMDD informat can read.  So something like 2022-10-10 for example.  Then your INPUT statement might look more like:

input dob yymmdd10.  dov yymmdd10. wt  21-26  ht 27-30 peri 31-35 
      endo 35-40 tibia 41-44 tanner 45 sex 46
;

And you will probably also want to attach a FORMAT to DOB and DOV so that they print in a style that is easier for humans to understand than values like 22,928 or -21,914.

format dob dov yymmdd10.;

If you really don't know how the dates are represented (or they are inconsistent) then you could try using the ANYDTDTE. informat instead.  That will try to guess what type of style the strings are using and adjust.

 

 

And if you want to make a PERMANENT dataset then don't want to use a one level dataset name. Instead create a libref that points to some directory on your machine and use a two level name.

libname perm "\\apporto.com\dfs\GWU\Users\kennedyhinnant_gwu\Downloads\Assignment 4\";
data perm.bone;
  infile "\\apporto.com\dfs\GWU\Users\kennedyhinnant_gwu\Downloads\Assignment 4\bone.txt" truncover;
  input dob yymmdd10.  dov yymmdd10. wt  21-26  ht 27-30 peri 31-35 
    endo 35-40 tibia 41-44 tanner 45 sex 46
  ;
  format dob dov yymmdd10.;
  age = (dov - dob)/365;
  logperi = log(peri);
run;

 

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 5 replies
  • 758 views
  • 0 likes
  • 4 in conversation