Why does comma9.2 not work? - sas

Can anyone tell me why comma9.2 is not working in my sas codes?
data have;
input x $16.;
y = input(x, comma9.2);
z = input(x, comma9.);
put x= y= z= ;
cards;
1,740.32
5200
520
52
7,425
9,000.00
36,000.00
;
run;

To expand on Reeza's answer:
Informat decimal places do not quite work the way Format decimal places do. In almost all cases, you will not want to or need to specify the d in the informat. Comma9. is almost always correct, no matter how many decimal places you expect - even if you expect always two.
The only use informat decimal places serve is when you have a number like 12345600, which has no decimal in it, but it ought to (the last two zeros are after the decimal).
data _null_;
input numval 8.2;
put numval=;
datalines;
12345600
12345605
99999989
1857.145
;;;;
run;
This was something that was common once upon a time in the age of punch cards, particularly for accounting; since everything was in dollars and cents, you could save a column by leaving out the decimal, and just read everything in with two decimals. It is no longer common in most fields (at least in my experience), but SAS is always backwards compatible.
SAS will ignore the .d specification if it encounters a decimal point in the data (and will then use the location of that decimal to read in the value correctly), but if there are no decimal points in the data it may read it in incorrectly if you specify the .d. Notice in my example the final row has a decimal point followed by three decimal places, and is read in correctly.
You can read SAS Documentation for more information.

Comma9.2 assumes that values will always have 2 decimal places.

Related

In SAS, how would I remove a decimal from a value?

I have a few million rows, where a particular columns’ values are showing as I.e. ###.## and I’d like them to show them as #####.
How can I modify this in the INFILE statement?
Thanks.
It you made the mistake of including a decimal width on in INFORMAT then that might be the cause of what you are seeing. The decimal width on an informat is for letting SAS know where the implied decimal place should be placed. You only want to do that when you know that your source strings were purposely generated without a period to mark the decimal place to save one character.
Example:
data have;
input #1 right 10. #1 wrong 10.3 ;
cards;
1.2
1234
;
Result:
Obs right wrong
1 1.2 1.200
2 1234.0 1.234

SAS Input: Dollar Amounts in Billions

I have an input file with a lot of dollar amounts given like this:
$433.5B $41.1B $331.1B $407.4B
$110.8B $19B $2,265.8B $170.1B
where the 'B' character stands for "billions". I do not have other suffixes like M or k. I need to read in this file using an INPUT statement in SAS inside a DATA step, and these figures should be numerics. There are several challenges to overcome, as well as a couple of features of the data to note:
There are dollar signs everywhere.
Some of the numbers have decimal points, and some don't, so we're dealing with variable-length data.
There are commas inside the numbers, such as $2,265.8B.
The most pesky aspect of this data are the B's after each amount.
The B's are always in the same columns.
What informat should I use to read in this numerical data?
I thought of using something along the lines of :DOLLAR4.1, like this:
Data bigcompanies;
Infile 'path\bigcompanies.dat' MISSOVER;
Input (sales profits assets market_value) (:DOLLAR4.1);
Run;
but it gives me nothing (as in, I get periods for those numbers). I don't know how to handle the B, which is, I think, the crux of the problem. The SAS documentation on the DOLLAR informat is rather sparse, unfortunately.
Many thanks for your help!
If the data is in fixed columns then just skip the columns where the B appears.
data test;
input sales dollar6. +1 profits dollar8. +1 assets dollar9. +1 market_value dollar9. +1 ;
*---+---10----+---20----+---30----+---40 ;
cards;
$433.5B $41.1B $331.1B $407.4B
$110.8B $19B $2,265.8B $170.1B
;
proc print;
run;
Results
market_
Obs sales profits assets value
1 433.5 41.1 331.1 407.4
2 110.8 19.0 2265.8 170.1
Note that you normally never want to add a decimal part to an informat. That is telling SAS where to place the decimal point when it does not appear in the source text. So "integers" will be divided by that power of 10.

w.d format incorrectly handling integers

I have a column which range from 0 to 1. Most of the values are decimals but some values are exactly 1. When I format the column to 10.4 for example, the 1s get converted to 0.0001 rather than 1.0000! Why is this happening???
INFORMAT
probability_of_default 7.4
....
;
FORMAT
probability_of_default 7.4
....
;
INPUT
probability_of_default
;
Sounds like you what you did was read the data using an INFORMAT of 10.4, instead of displaying the data using a FORMAT of 10.4. If you specify the decimal part of an informat then you are telling SAS that when there is no decimal point in the text that it is reading to assume there is one at d characters before the end. So you told SAS to divide the integers by 10**4. Instead just use an informat without any decimal part, like 10., instead of 10.4.

Decimal to Hex to Decimal

im reading in some data where numbers that were originally hex have been read in as decimal.
As these hex examples are all also valid decimal numbers, when I have read them in from a text file SAS has read then as decimal.
Examples are 53 and 68, which are the hex numbers for 83 and 104 decimals respectively.
Using the hex2. format converts 53 and 68 into hex numbers (68 becomes 44 for example), which is not what I want.
Is there away to get SAS to recognise 53 and 68 as hex without trying to convert them to hex?
Use the informat hexw.. Recall that informats and formats are different.
Informat
An informat is a type of SAS language element that applies a pattern to or executes instructions for a data value to be read as input.
Format
A format is a type of SAS language element that applies a pattern to
or executes instructions for a data value to be displayed or written
as output.
A good way to remember it:
A format is how you see it
An informat is how SAS internally sees it
Explanation
Informats are used to convert input values to something that SAS can appropriately perform mathematical operations on. For example,
01JAN2015
By itself, it's just a character string. SAS doesn't know how to perform math on 01JAN2015, and it will read the value in as a character string automatically. But, SAS does know how to interpret what that string represents. You just need to tell SAS to interpret it in a certain way.
For SAS to do math on dates, it uses a reference date of 1/1/1960. By applying the informat date9., SAS is able to understand that the string represents the 20,089th day since 1/1/1960. The output will then look as such:
20089
That's hard for people to read. You can apply the mmddyy10. format to this so that you can read it, but SAS can also understand it. Format will not change what SAS sees. The value is still stored as a decimal, but the way it's displayed to you is more readable.
**To SAS** **To you**
date date
20089 01/01/2015
In your case, SAS knows the value you're reading is numeric. It will automatically assume it's a decimal, but we know for a fact that it is not.
Following the above logic, we want to apply an informat to the numeric values so SAS will interpret the values as hex, and not decimals.
data want;
informat hex_value hex2.;
input hex_value;
datalines;
53
68
;
run;
Your table will look as such:
hex_value
83
104
If you apply the format hex2., you'll see the output table as hex again. Since we've already interpreted the value, we're just changing how it looks to you, but not how it looks to SAS:
**To SAS** **To you**
hex_value hex_value
83 53
104 68

Converting CHAR to NUM with varying decimal places

I am trying to convert a column stored from character to numeric. The problem is that this column has varying number of decimal places.
For example,
Data
1052969525
392282764.234
221018301.2
130010764.7894
82340150
183779233.4
I have determined that the likely maximum of decimal places is 4, the width required would be about 15. So I have attempted the following:
datanum = input(data, 15.4);
But this appears to put the decimal place in the wrong place, especially for those that have no decimal places. What is the most reasonable way to convert this column from char to numeric? This column is part of a database table uploaded by someone else so there's not much option to change that. Thanks.
You don't normally supply the decimal width in informats. For a normal number, you only supply the width, and SAS will figure out the decimal for you (based on the position of the decimal point).
datanum = input(data,15.);
The .d part of an informat is to allow for compatibility with (mostly) older systems that did not have decimals in the data, to save space. For example, if I'm reading in money amounts, and I only have 6 spaces:
123456
882348
100000
123400
I can read that in as an integer amount of cents - or I can do:
input cost 6.2;
That will then tell SAS to place the decimal before the last 2 characters.