SAS Programming

DATA Step, Macro, Functions and more
BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Hello_there
Lapis Lazuli | Level 10

Hi, I'm trying to figure out the coding for how I can format this data set into 3 significant figures with the exact presentation listed below. 

 

Thanks

 

data have;
	input x;
datalines;
31.45
0.02355
0.45
34
4723
;
run;

Want:

Hello_there_0-1665129257233.png

 

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hi @Hello_there,

 

You could create a format based on a user-defined function:

data have;
input x;
datalines;
31.45
0.02355
0.45
34
4723
-9994.999
-9995
-1.235e-15
0
9.876e15
9.999e15
.
.A
;

proc fcmp outlib=work.funcs.test;
function sig3dig(x) $32;
  length f $32;
  if x then do;
    m=floor(log10(abs(x)));
    y=round(x,10**(m-2));
    m=floor(log10(abs(y)));
    f=if m>1 then left(put(y,32.))
             else left(putn(y,cat('32.',2-m)));
  end;
  else f=put(x,1.);
  return(f);
endsub;
run;

options cmplib=work.funcs;

proc format;
value sig3dig (default=32)
other=[sig3dig()];
run;

proc print data=have;
format x sig3dig.;
run;

 

This should work for numbers with absolute values in a range from about 1E-15 through 1E16. (I assume that the "31.6" in your sample output is a typo and should read 31.5.)

View solution in original post

8 REPLIES 8
Mike_j
SAS Employee

I am not entirely sure what format you want to add, as the data has changed in various different way.

 

If what you are asking, is to have 3 decimals then a format like this should do the job:

data want;
set have;
format x comma10.3;
run;

This will give you this result:

Mike_j_0-1665148550886.png

 

 

 

Hello_there
Lapis Lazuli | Level 10
Hey Mike, thanks for the reply. The final result I'm looking for is how I have it screenshot in the original post. There is some code doing a quick online search on how to get 3 significant figures, but the difficulty I'm having is attaching 1 zero at the end of the values in row 3 and row 4. I'm sure there has to be some kind of conditional logic I have to use to be able to do it, but I was looking for a more efficient way.


Tom
Super User Tom
Super User

@Hello_there wrote:
Hey Mike, thanks for the reply. The final result I'm looking for is how I have it screenshot in the original post. There is some code doing a quick online search on how to get 3 significant figures, but the difficulty I'm having is attaching 1 zero at the end of the values in row 3 and row 4. I'm sure there has to be some kind of conditional logic I have to use to be able to do it, but I was looking for a more efficient way.



How do you know the zeros belong at the end of the third and fourth values? 

That is :

How do you know that 0.45 was measured to the thousandths place and not the hundreds place?

And how do you know that 34 was measured to the tenths place instead of the ones place?

FreelanceReinh
Jade | Level 19

Hi @Hello_there,

 

You could create a format based on a user-defined function:

data have;
input x;
datalines;
31.45
0.02355
0.45
34
4723
-9994.999
-9995
-1.235e-15
0
9.876e15
9.999e15
.
.A
;

proc fcmp outlib=work.funcs.test;
function sig3dig(x) $32;
  length f $32;
  if x then do;
    m=floor(log10(abs(x)));
    y=round(x,10**(m-2));
    m=floor(log10(abs(y)));
    f=if m>1 then left(put(y,32.))
             else left(putn(y,cat('32.',2-m)));
  end;
  else f=put(x,1.);
  return(f);
endsub;
run;

options cmplib=work.funcs;

proc format;
value sig3dig (default=32)
other=[sig3dig()];
run;

proc print data=have;
format x sig3dig.;
run;

 

This should work for numbers with absolute values in a range from about 1E-15 through 1E16. (I assume that the "31.6" in your sample output is a typo and should read 31.5.)

Hello_there
Lapis Lazuli | Level 10
Thanks, FreelanceReinhard!

This code does the job and I appreciate it. This type of coding is new stuff that I've never seen before, so it gives me an opportunity to learn what it does.

Thanks again!
Hello_there
Lapis Lazuli | Level 10

Hi @FreelanceReinh , is there a way to make this function dynamic, so that i can have an argument for the number of significant digits i want it to extend to? For example, this function goes out 3 places only. Do you know how i would be able to have it in case i wanted to go out to only 2 places or 4 places?

 

Thanks

FreelanceReinh
Jade | Level 19

Hi @Hello_there,

 

Yes, we can add the number n of significant digits as the first argument:

proc fcmp outlib=work.funcs.test;
function sigdig(n, x) $32;
  length f $32;
  if x then do;
    m=floor(log10(abs(x)));
    y=round(x,10**(m-n+1));
    m=floor(log10(abs(y)));
    f=if m>n-2 then left(put(y,32.))
             else left(putn(y,cat('32.',n-1-m)));
  end;
  else f=put(x,1.);
  return(f);
endsub;
run;

options cmplib=work.funcs;

(Changes to the definition of sig3dig are highlighted in boldface.)

 

Test of the new function using the HAVE dataset from the original solution:

data want;
set have;
x1=sigdig(1,x);
x2=sigdig(2,x);
x3=sigdig(3,x);
x4=sigdig(4,x);
x5=sigdig(5,x);
x9=sigdig(9,x);
run;

 

Note that we cannot use the new function in a PROC FORMAT step because it requires two arguments. But we could define separate functions sig1dig, sig2dig, etc. and corresponding formats.

Hello_there
Lapis Lazuli | Level 10

Hi @FreelanceReinh ,

 

Thanks, this is an amazingly elegant solution for my use case.

 

Much appreciated!

sas-innovate-white.png

Our biggest data and AI event of the year.

Don’t miss the livestream kicking off May 7. It’s free. It’s easy. And it’s the best seat in the house.

Join us virtually with our complimentary SAS Innovate Digital Pass. Watch live or on-demand in multiple languages, with translations available to help you get the most out of every session.

 

Register now!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 3595 views
  • 4 likes
  • 4 in conversation