Skip to content

Instantly share code, notes, and snippets.

@daynebatten
Last active August 29, 2015 14:20
Show Gist options
  • Select an option

  • Save daynebatten/ddc6e706302c7c5e04fe to your computer and use it in GitHub Desktop.

Select an option

Save daynebatten/ddc6e706302c7c5e04fe to your computer and use it in GitHub Desktop.
/* target_data is the data set you want to suppress
dimensions is a pipe-separated list of dimensions to suppress */
%macro constraints(target_data, dimensions);
/* Count the number of dimensions we're working with */
%let num_dims = %eval(%sysfunc(count(&dimensions, |)) + 1);
/* Build a macro variable array with the dimension names */
%do i = 1 %to &num_dims;
%let dim&i = %sysfunc(scan(&dimensions, &i, |));
%end;
/* We need constraints for every combination of dimensions you can build by leaving out one dimension at a time.
This is pretty simple in a 2-dimensional dataset. */
proc sql;
create table
levels
%do i = 1 %to &num_dims;
/* If this is the first loop through, we don't need the "union all"... */
%if &i = 1 %then %do;
as
%end;
%else %do;
union all
%end;
select distinct
/* Include every dimension but the one we're leaving out. That one will just get a placeholder. */
%do j = 1 %to &num_dims;
%if &j = &i %then %do;
'dummy' as &&dim&j
%end;
%else %do;
&&dim&j
%end;
/* Add a comma unless it's the last dimension in the list */
%if &j < &num_dims %then %do;
,
%end;
%end;
from
&target_data
%end;
/* Semicolon for the end of our SQL statement */
;
quit;
/* Assign numbers to our soon-to-be constraints */
data levels;
set levels;
con = _n_;
run;
/* Merge our raw data with our constraint categories to determine which constraints apply to which data points */
proc sql;
create table
joined
as select
t.*,
con,
case when
%do i = 1 %to &num_dims;
/* If it's not the first loop, we need an "or" */
%if &i > 1 %then %do;
or
%end;
/* We'll want to evaluate on a match across any set of all dimensions but one */
/* Start by opening our paren to keep the logic right */
(
%do j = 1 %to &num_dims;
/* Need an "and" unless this is the first loop */
%if &j > 1 %then %do;
and
%end;
/* If this is the dimension we're leaving out, look for a placeholder */
/* Otherwise, look for a real match on the dimension */
%if &i = &j %then %do;
l.&&dim&j = 'dummy' and t.&&dim&j ~= 'ALL'
%end;
%else %do;
l.&&dim&j = t.&&dim&j
%end;
%end;
/* Close our paren */
)
%end;
then 1 else 0 end as included
from
&target_data as t
left join
levels as l
on
1 = 1;
quit;
/* Sort so we can transpose */
proc sort data = joined;
by
%do i = 1 %to &num_dims;
&&dim&i
%end;
;
run;
/* And transpose! */
proc transpose data = joined out = constraints(drop = _NAME_) prefix = con;
by
%do i = 1 %to &num_dims;
&&dim&i
%end;
;
id con;
var included;
run;
%mend;
%constraints(Testset,degree|county);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment