I have some sample data below and I need to find the scenario where the value is closest to but no greater than 94,000,100. The answer would be 12. How do I accomplish this in SAS? This is a piece of code within a large SAS program. Any input is greatly appreciated!
1
Perhaps first filter the data to be less than or equal to the target N
(here, N = 94,000,100) and then pick the maximum of those. Something like this:
select scenarios, rank, value
from proclib.datatable
where value <= &N
having value = max(value)
SAS does not require a group by
for using having
.
If your data is sorted descending by value, then simply read the data until you hit a value less than 94,000,100. Then save the scenario in a macro variable
data have;
input scenario rank value;
format comma20;
datalines;
189 1 100500000
27 2 100000000
57 3 99500000
159 4 99000000
103 5 98500000
113 6 98000000
176 7 97500000
108 8 97000000
184 9 96500000
80 10 96000000
105 11 95500000
58 12 95000000
12 13 94000000
138 14 93000000
185 15 92000000
;
%let v = 94100000;
data _null_;
set have;
if value < &v. then do;
call symputx('closest_scenario', scenario);
stop;
end;
run;
%put &=closest_scenario.;
0
The overkill method: solving it with linear programming. Totally unnecessary but a fun exercise nonetheless. This program finds the minimum difference between the number and the max value that it cannot exceed.
proc optmodel;
set <num> scenario;
num value{scenario};
num max_val = 94000100;
read data have into scenario=[scenario] value;
var x{scenario} binary;
/* Only select one value */
con select_one: sum{s in scenario} x[s] = 1;
/* The selected value must <= the maximum value */
con le_max {s in scenario}: x[s]*value[s] <= max_val;
/* Minimize the difference from the max value */
min closest = max_val - sum{s in scenario} (x[s]*value[s]);
solve;
print x value;
run;
Thank you for your suggestions! This is what I ended up with. The code in the parenthesis filtered the data to only include values that are no larger than the specified number &v and then take the maximum of those values. This is the record that is closest to but not greater than &v. I then use “select…into” to write the scenario number into a macro variable “scen”.
select scenario
into :scen trimmed
from (select scenario, value
from have
where value le &v.
having value=max(value));
%put &scen;
1