Suppose I have the following dataset:
data df;
input frac $;
datalines;
1/3
1/4
5/12
1
0
7/12
;
run;
And I want to get to this:
frac
0.33
0.25
0.42
1.00
0.00
0.58
I know I could get this output by doing this:
proc sql;
select
case
when frac = '1/12' then 0.083
when frac = '1/6' then 0.167
...
end as frac_as_num
from df
;
quit;
But I'd rather not hard-code everything. I know I could do something like this in Python:
frac = ['1/12', '1/6', ...]
[eval(f) for f in frac]
something like below using scan and input should work.
proc sql;
create table want as
select frac,
case when index(frac,'/') then
input(scan(frac, 1),best32.)/input(scan(frac, 2),best32.)
else input(frac,best32.) end as frac_as_num format= 5.2
from df;
This is how I would do it so that the results are numbers and have not been converted to and from character which would happen if you use %SYSEVALF via RESOLVE in a single step.
filename FT76F001 temp;
data _null_;
file FT76F001;
input frac $;
put +3 'x=' frac ';' frac=$quote. '; output;';
datalines;
1/3
1/4
5/12
1
0
7/12
;
run;
data frac;
length x 8 frac $16;
%inc FT76F001;
run;
proc print;
run;
This is using SYSEVALF
464 data _null_;
465 input frac $;
466 x = input(resolve(cats('%sysevalf(',frac,')')),f32.);
467 put 'NOTE: ' (_all_)(=);
468 datalines;
NOTE: frac=1/3 x=0.3333333333
NOTE: frac=1/4 x=0.25
NOTE: frac=5/12 x=0.4166666667
NOTE: frac=1 x=1
NOTE: frac=0 x=0
NOTE: frac=7/12 x=0.5833333333
I'd say the simplest way to do it would be to put your fractional value into a macro variable, call the sysevalf
function on it to evaluate the value, and finally convert it back into a normal variable. This has the added benefit of being able to work with any math expression, not just fractions.
Something like:
data test;
set df;
call symput('myMacroVariable',frac); /* Put the value of frac into a macro variable */
dec = resolve('%sysevalf(&myMacroVariable)'); /* Evaluate the value of the macro variable */
run;
Edit: Don't listen to me, data_null_'s answer does the same thing but in one line.
data df;
input frac $;
_frac=put(scan(frac,1)/coalesce(scan(frac,2),1),4.2);
datalines;
1/3
1/4
5/12
1
0
7/12
;
run;