BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
StephenM
Fluorite | Level 6

Hello,

 

I need to create a format which formats to 2 decimal places whilst rounding to the nearest even number i.e. it will print the number 8.665 as 8.66 rather than 8.67.

 

I have begun by following the advice in this thread and created a custom format which uses a function to do the format. What I have so far is this..

 

proc fcmp outlib=work.func.sample;
  function nre(value);
    return( rounde(value, 0.01) );
  endsub; 
run; 

* make function available;
options cmplib=work.func;

* create a format that uses the function;
proc format; 
  value rex
    low - high = [nre()]
  ;
run; 

The problem I have is that my custom format rex will round correctly but will not display to two decimal places i.e. it drops trailing zeroes and prints 4.00 as 4. Any help in getting to the final step would be much appreciated.

 

Also, right now I only need to perform this to two decimal places but often need to round to an arbitrary number of places. Is there a way to generalise this code to allow me to select the number of places to round to without having to create a newformat

 

Thanks,

Steve

1 ACCEPTED SOLUTION

Accepted Solutions
ChrisHemedinger
Community Manager

How about something like this, which gives you more control over the formatted value as a displayed value.

 

proc fcmp outlib=work.func.sample;
  function nre(value) $;
    return( put(rounde(value, 0.01),5.2) );
  endsub; 
run; 

* make function available;
options cmplib=work.func;

* create a format that uses the function;
proc format; 
  value rex
    low - high = [nre()]
  ;
run; 

data n;
 length x 8 y 8 z 8;
 x = 4.00;
 y = 4.536;
 z = 1.625;
 format x rex. y rex. z rex.;
run;
Obs     x       y       z
 1     4.00    4.54    1.62
Learn from the Experts! Check out the huge catalog of free sessions in the Ask the Expert webinar series.

View solution in original post

10 REPLIES 10
Reeza
Super User

Why not use the round function? 

 

Try round( variable, 0.02);

 

If you really want a format check the SAS docs about creating a format based on a function. There's an example in the docs. 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Use the appropriate function to manipulate your data.  Formats are for changing how a variable is displayed, whilst retaining the real value underneath.  The two ways are different.  Sending data which is hidden behind a format like this would to me, be quite bad practice.  If the value is to be round, use round, if it is not, then show the full value.  Otherwise your just obfuscating your data.

StephenM
Fluorite | Level 6

The bigger picture is that I'm trying to format values as they come out of a PROC TABULATE procedure without having to put them through another data step. Normally this is something I would do in the data step but constraints on this particular project means I'd like to do to this with format.

 

Also I'm not sure I agree that this constitutes bad practice or obfuscating the data underneath. After all, SAS is already rounding the value it presents when using the w.d format I would normally use. All I'm trying to do is make SAS use a different rounding method.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Hi,

 

Rounding is a different concept to formatting, maybe the terminology you use means something different?  To round a number, you take the value and physically change that value in the dataset.  Formatting a variable does not physically change the value, only the way it is displayed.  So:

Actual value = 1.36

Rounded value = 1.4

Formatted value (as shown in table view) = 1.3

Actual value if format is removed = 1.36

 

I rarely use tabulate if at all any more, so can't really help much with syntax there, but you get a table out from your statement do you not, or does that goto an output file directly?  

Seems to me like your saving on a couple of lines of data step code after the effect, but vastly expanding your code to encompass formats, and functions etc.

StephenM
Fluorite | Level 6

Hi,

 

I think you are right that we are talking about different types of rounding. 

What I might call "data rounding" is when you change the value of the underlying value using a round function. So for example if x = 1.625, then rounde(x,0.01) = 1.620.

 

What I might call "format rounding" is the rounding that SAS applies to the value it displays whilst keeping the underlying value the same.

So if I have a value of 1.625 and apply the 6.2 (the w.d format), then SAS will display this as 1.63 whilst the underlying value of 1.625 is retained. So SAS has "Format rounded" the formatted value of 1.625 to 1.63.

 

What I want to do is choose the type of rounding SAS does to the formatted value. By default SAS rounds up (1.625 -> 1.63) but I want it to round to even  (1.625 -> 1.62).

 

The benefit of this is I could present the data in the way I need without changing the underlying value. Otherwise I would need to

1) Use Proc tabulate to create the table and output it as a data set.

2) Use a data step to round all the values using the rounde function

3)Use Proc report to output this dataset to a PDF.

 

What I want to do is

1) Use proc tabulate to create the PDF directly with the values already rounded the correct way.

 

Hope this clarifies what I am trying to do. Thanks for your input so far.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Mmm, sorry, I don't know on that.  My preferred approach is to always go 1), 2) (these two could be combined), 3) proc report.  I have never come across a procedure which generates exactly theright output for what I want.  Maybe you can emulate the tabulate code in proc report (or just emulate it in a datastep, i.e. datastep does processing, then proc report - this is what I tend to do as never found a procedure which produces exactly the output I require).

ChrisHemedinger
Community Manager

How about something like this, which gives you more control over the formatted value as a displayed value.

 

proc fcmp outlib=work.func.sample;
  function nre(value) $;
    return( put(rounde(value, 0.01),5.2) );
  endsub; 
run; 

* make function available;
options cmplib=work.func;

* create a format that uses the function;
proc format; 
  value rex
    low - high = [nre()]
  ;
run; 

data n;
 length x 8 y 8 z 8;
 x = 4.00;
 y = 4.536;
 z = 1.625;
 format x rex. y rex. z rex.;
run;
Obs     x       y       z
 1     4.00    4.54    1.62
Learn from the Experts! Check out the huge catalog of free sessions in the Ask the Expert webinar series.
RW9
Diamond | Level 26 RW9
Diamond | Level 26

My point exactly Chris.  How is all that code a saving against a simple datastep after the effect?  Its basically hiding the rounding in a compiled procedure behind a format?

StephenM
Fluorite | Level 6

Thanks!

 

I've been able to use this code as a basis to create a set of formats rounding evenly to different decimal places, which should save me a lot of time in the future.

 

In answer to some of the other questions, rounding to even only applies in the case of tie breakers e.g. the third decimal place is 5 when your rounding to 2d.p.

Therefore 1.615-> 1.62, 1.625->1.62. All other cases would be rounded as you would normally expect, so 1.633->1.63.

 

From what I know, rounding to even is the statistically safer way of rounding. It is also the way R rounds by default which is why I need to achieve the same in SAS.

Ksharp
Super User

What you gonna do with odd number like : 1.633 ?

 

proc format;
picture rex
 other='009.99' ;
run;

data n;
 length x 8 y 8 z 8;
 x = 4.00;
 y = 4.536;
 z = 1.625;
 format x y z rex.;
run;

SAS Innovate 2025: Call for Content

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!

Submit your idea!

What is Bayesian Analysis?

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 10 replies
  • 5897 views
  • 2 likes
  • 5 in conversation