#/******************* URBAN INSTITUTE MACRO LIBRARY *********************
#
# Macro: Adjust_count_totals
# Description: Adjusts a list of integer count variables against a
# control total.
#
# Use: Open code
#
# Author: Peter Tatian
#
# ***********************************************************************
Adjust_count_totals(
%macro in_ds=, #/** Input data set **/
out_ds=, #/** Output data set **/
control_total=, #/** Control total var **/
counts=, #/** Count vars **/
comp_op=EQ, #/** Comparison operator **/
debug=N, #/** Print debugging info **/
quiet=Y #/** Suppress LOG notes **/
);
#/*************************** USAGE NOTES *****************************
#
# SAMPLE CALL:
# %Adjust_count_totals(
# in_ds=Test_adjust_count_totals,
# out_ds=Adjust_count_results,
# control_total=total,
# counts=a b c d,
# comp_op=eq,
# debug=y,
# quiet=n
# )
# adjusts count vars a b c and d so that their sum equals total
# *********************************************************************/
***** ***** ***** MACRO SET UP ***** ***** *****;
%
%local ;
***** ***** ***** ERROR CHECKS ***** ***** *****;
%
***** ***** ***** MACRO BODY ***** ***** *****;
%
&out_ds;
data
&in_ds end=_act_last_obs;
set
if _n_ = 1 then do;
/ "NOTE (Adjust_count_totals): Adjusting counts where " @;
put "%upcase( &control_total &comp_op sum( of &counts ) ) " @;
put "is not true." /;
put
end;
*} &counts;
array _act_array{
** Copy original count values into separate array **;
32767} _temporary_;
array _act_array_org{
= 1 to dim( _act_array );
do _act_i = _act_array{_act_i};
_act_array_org{_act_i}
end;
** Initialize total vars **;
= &control_total;
_act_ctrl_total = sum( of _act_array{*} );
_act_sum_array
%if %mparam_is_yes( &debug ) %then %do;
/ "INPUT DATA" // _n_= _act_ctrl_total= _act_sum_array= ;
put put (&counts) (=);
****%put_array( _act_array );
%end;
if _act_sum_array ~= 0 and _act_ctrl_total >= 0 and not( _act_ctrl_total &comp_op _act_sum_array ) then do;
%if %upcase( &quiet ) = N %then %do;
"NOTE (Adjust_count_totals): Adjusting counts for obs. " _n_;
put
%end;
Sort_array_ref( _act_array, quiet=y, order=descending );
%
= 1 to dim( _act_array );
do _act_i = round( _act_array{ _act_i } * ( _act_ctrl_total / _act_sum_array ) );
_act_array{ _act_i }
end;
= sum( of _act_array{*} );
_act_sum_array = _act_sum_array - _act_ctrl_total;
_act_diff
%if %mparam_is_yes( &debug ) %then %do;
/ "STEP 1" // _act_ctrl_total= _act_sum_array= _act_diff= ;
put put (&counts) (=);
****%put_array( _act_array );
%end;
if _act_diff ~= 0 then do;
****[7/2/03] %Sort_array_ref( _act_array, quiet=y, order=descending );
= 1 to dim( _act_array );
do _act_i
****[7/2/03] if _act_array{ _act_array_srtd{ _act_i } } > 0 then do;
if _act_array_org{ _act_array_srtd{ _act_i } } > 0 then do;
if _act_diff > 0 then
=
_act_array{ _act_array_srtd{ _act_i } } -
_act_array{ _act_array_srtd{ _act_i } } min( _act_array{ _act_array_srtd{ _act_i } }, _act_diff );
else if _act_diff < 0 then
=
_act_array{ _act_array_srtd{ _act_i } } - _act_diff;
_act_array{ _act_array_srtd{ _act_i } }
= sum( of _act_array{*} );
_act_sum_array = _act_sum_array - _act_ctrl_total;
_act_diff
if _act_diff = 0 then go to exit_loop;
end;
end;
:
exit_loop
end;
end;
= sum( of _act_array{*} );
_act_sum_array
%if %mparam_is_yes( &debug ) %then %do;
/ "FINAL" // _act_ctrl_total= _act_sum_array= _act_diff= ;
put put (&counts) (=);
****%put_array( _act_array );
%end;
: ;
drop _act_
run;
***** ***** ***** CLEAN UP ***** ***** *****;
%
%mend Adjust_count_totals;
/************************ UNCOMMENT TO TEST ***************************
** Autocall macros **;
"K:\Metro\PTatian\UISUG\Uiautos";
filename uiautos =(uiautos sasautos);
options sasautos
options mprint nosymbolgen nomlogic;"Adjust_count_totals: SAS Macro Library";
title
data Test_adjust_count_totals;
input total a b c d;
cards;100 40 30 0 10
100 47 1 1 1
100 50 40 0 20
10 4 3 0 1
10 5 4 0 2
1 0 10 11 2
1 0 100 101 20
;
run;Adjust_count_totals(
%in_ds=Test_adjust_count_totals,
out_ds=_null_,
control_total=total,
counts=a b c d,
comp_op=eq,
debug=y,
quiet=n
)
/**********************************************************************/
Adjust Count Totals
Purpose: Adjusts a list of integer count variables against a control total.