- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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:
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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:
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
@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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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!
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi @FreelanceReinh ,
Thanks, this is an amazingly elegant solution for my use case.
Much appreciated!