* 1.0 Jared Colston March 2022

* Program for creating Waffle Charts



capture program drop waffle
program waffle
version 17

syntax varlist(numeric min=1 max=5) [if] [in], ///
	[WIDE BY(passthru) Title(str) COLORs(str) ///
	EMPTYcolors(str) OUTLinecolors(str) EMPTYOUTLinecolors(str) ///
	SCHeme(str) Note(str) MARKersize(numlist min=1 max=1) ///
	BYRows(numlist min=1 max=1) NAME(passthru) ///
	LEGend(passthru) COOLSgraph]

preserve																			// Store original data
quietly {
	tokenize `varlist'																// Define the varlist in macros
	marksample touse
	if "`missing'" == "" markout `touse', strok
	count if `touse'
	if r(N) == 0 exit 2000
	capture keep if `touse' == 1													// Allow "if" conditions

	*cool s graph easter egg. This is just a silly add-on
		if "`coolsgraph'" != "" {
			di as err "You just drew a Cool S Graph! Nice! Only this time not on your middle school textbook."
			graph twoway scatteri 3 9 8 9, lcolor(red) recast(line) ///
			yscale(range(0 20)) xscale(range(0 20)) ylabel(, nogrid noticks nolabel) ///
			xlabel(, nogrid noticks nolabel) legend(off) ytitle("") xtitle("") ///
			|| scatteri 3 10 8 10, lcolor(red) recast(line) ///
			|| scatteri 3 11 8 11, lcolor(red) recast(line) ///
			|| scatteri 10 9 15 9, lcolor(red) recast(line) ///
			|| scatteri 10 10 15 10, lcolor(red) recast(line) ///
			|| scatteri 10 11 15 11, lcolor(red) recast(line) ///
			|| scatteri 15 9 18 10, lcolor(red) recast(line) ///
			|| scatteri 18 10 15 11, lcolor(red) recast(line) ///
			|| scatteri 3 9 1 10, lcolor(red) recast(line) ///
			|| scatteri 1 10 3 11, lcolor(red) recast(line) ///
			|| scatteri 10 9 8 10, lcolor(red) recast(line) ///
			|| scatteri 10 10 8 11, lcolor(red) recast(line) ///
			|| scatteri 8 9 8.5 9.5, lcolor(red) recast(line) ///
			|| scatteri 10 11 9.5 10.5, lcolor(red) recast(line)
			exit 198
		}

	// GENERAL OPTIONS
		*assign titles based on "by" option
			if "`title'" != "" {
				local title_by "`title'"
				local title_noby "`title'"
			}

		*define colors of markers
			if "`colors'" != "" {
				local mcolor1 : word 1 of `colors'
				local mcolor2 : word 2 of `colors'
				local mcolor3 : word 3 of `colors'
				local mcolor4 : word 4 of `colors'
				local mcolor5 : word 5 of `colors'
			}

			else {
				local mcolor1 "78 121 167"
				local mcolor2 "242 142 43"
				local mcolor3 "89 161 79"
				local mcolor4 "176 122 161"
				local mcolor5 "255 157 167"
			}

			if "`emptycolors'" != "" {
				local ecolor "`emptycolors'"
			}

			else {
				local ecolor "gs14"
			}

		*define outline colors of markers
			if "`outlinecolors'" != "" {
				local ocolor "`outlinecolors'"
			}

			else {
				local ocolor "none"
			}

			if "`emptyoutlinecolors'" != "" {
				local eocolor "`emptyoutlinecolors'"
			}

			else {
				local eocolor "none"
			}

		*allow scheme
			if "`scheme'" != "" {
				local scheme "`scheme'"
			}

		*allow note
			if "`note'" != "" {
				local note "`note'"
			}

		*parse byvar from passthru code
		if "`by'" != "" {
			local byvar `by'
			local byvar : subinstr local byvar "by(" "", all
			local byvar : subinstr local byvar ")" "", all
			local byvar : subinstr local byvar "," " ", all
			local byvar : word 1 of `byvar'

			*convert byvar to numeric if string
			local byvartype : type `byvar'
			if substr("`byvartype'",1,3) == "str" {
				encode `byvar', gen(`byvar'_waf)
				local byvar `byvar'_waf
			}
		}

	// IF ONLY ONE VARIABLE SPECIFIED
	if "`2'" == "" & "`3'" == "" & "`4'" == "" & "`5'" == "" {

		capture keep `1' `byvar' `touse'
		capture duplicates drop `1' `byvar' `touse', force

		*transform values to decimals if not
			if `1' > 100 {
				di as err "Variable does not appear to be a percent or decimal (it is higher than 100)"
				exit 198
			}

			if `1' > 1 {
				replace `1' = (`1' / 100)
			}

		*waffle structure
			if "`wide'" != "" {
				local rows = 20
				local cols = 5
				local aspectratio = .20
				local msize = 5
			}

			else if "`wide'" == "" {
				local rows = 10
				local cols = 10
				local aspectratio = 1
				local msize = 7
			}

		local obsv = `cols' * `rows'
		expand `obsv'

		*address issues with non-unique obs
			if "`by'" == "" & _N > 100 {
				di as err "Variable selection does not uniquely define percent. Try combining with by()"
				exit 198
			}

			duplicates report `1' `byvar'
			local unique_value = `r(unique_value)'
			gen unique_val = `unique_value'
			capture levelsof `byvar'
			capture local groups = `r(r)'
			capture gen groups = `groups'
			gen error_dummy = 0
			capture replace error_dummy = 1 if unique_val > groups
			if "`by'" != "" & error_dummy == 1 {
				di as err "Variable contains too many unique values. Your by() variable levels must match the number of unique values"
				exit 198
			}

		*by variables
			if "`by'" != "" {
				bysort `byvar' :	egen y = seq(), b(`cols')
								egen x = seq(), t(`cols')
				by `byvar' 	: 	gen id = _n
				egen tag = tag(`byvar')
				gen category = .
				local msize = 2
				levelsof `byvar', local(lvls)
				foreach x of local lvls {
					summ `1' if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace category = id <= int(`share' * `r(max)') if `byvar' == `x'
				}
			}

			else {
				egen y = seq(), b(`cols')
				egen x = seq(), t(`cols')
				gen id = _n
				gen category = .
				summ `1'
				local share = `r(mean)'
				summ id
				replace category = id <= int(`share' * `r(max)')
			}

		*reverse structure for wide
			if "`wide'" != "" {
				local y x
				local x y
			}

			else {
				local y y
				local x x
			}

		*allow msize
			if "`markersize'" != "" {
				local msize = `markersize'
			}

		*plot charts
			if "`by'" != "" {
				twoway	(scatter `y' `x' if `touse' & category == 1, 				///
							msymbol(square) mfcolor("`mcolor1'")					///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) 		///
						(scatter `y' `x' if `touse' & category == 0, 				///
							msymbol(square) mfcolor("`ecolor'") 					///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') 		///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio')			 			///
						by(, legend(off) noiyaxes noixaxes noiytick 				///
							noixtick noiylabel noixlabel note("`note'")				///
							title(`title_by')) `by'									///
						subtitle(, nobox) scheme(`scheme') `name')
			}

			else {
				twoway	(scatter `y' `x' if `touse' & category == 1, 				///
							msymbol(square) mfcolor("`mcolor1'") 					///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) 		///
						(scatter `y' `x' if `touse' & category == 0, 				///
							msymbol(square) mfcolor("`ecolor'") 					///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') 		///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio') title(`title_noby')	///
						scheme(`scheme') note("`note'") `name')
			}
	}

	// IF TWO VARIABLES SPECIFIED
	else if "`2'" != "" & "`3'" == "" & "`4'" == "" & "`5'" == "" {
		capture keep `1' `2' `byvar' `touse'
		capture duplicates drop `1' `2' `byvar' `touse', force

		*transform values to decimals if not
			if `1' > 100 | `2' > 100 {
				di as err "Variable does not appear to be a percent or decimal (it is higher than 100)"
				exit 198
			}

			if `1' > 1 {
				replace `1' = (`1' / 100)
			}

			if `2' > 1 {
				replace `2' = (`2' / 100)
			}

		*waffle structure
			if "`wide'" != "" {
				local rows = 20
				local cols = 5
				local aspectratio = .20
				local msize = 4
			}

			else if "`wide'" == "" {
				local rows = 10
				local cols = 10
				local aspectratio = 1
				local msize = 6
			}

		local obsv = `cols' * `rows'
		expand `obsv'

		*address issues with non-unique obs
			if "`by'" == "" & _N > 100 {
				di as err "Variable selection does not uniquely define percent. Try combining with by()"
				exit 198
			}

			/*
			duplicates report `1' `2' `byvar'
			local unique_value = `r(unique_value)'
			gen unique_val = `unique_value'
			capture levelsof `byvar'
			capture local groups = `r(r)'
			capture gen groups = `groups'
			gen error_dummy = 0
			capture replace error_dummy = 1 if unique_val > groups
			if "`by'" != "" & error_dummy == 1 {
				di as err "Variable contains too many unique values. Your by() variable levels must match the number of unique values"
				exit 198
			}
			*/

		gen seq_cat1 = `1'
		gen seq_cat2 = seq_cat1 + `2'

		*by variables
			if "`by'" != "" {
				bysort `byvar' :	egen y = seq(), b(`cols')
								egen x = seq(), t(`cols')
				by `byvar' 	: 	gen id = _n
				egen tag = tag(`byvar')
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				local msize = 2
				levelsof `byvar', local(lvls)

				foreach x of local lvls {
					summ seq_cat1 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat1 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat2 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat2 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}
			}

			else {
				egen y = seq(), b(`cols')
				egen x = seq(), t(`cols')
				gen id = _n
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .

				summ seq_cat1
				local share = `r(mean)'
				summ id
				replace color_cat1 = id <= int(`share' * `r(max)')

				summ seq_cat2
				local share = `r(mean)'
				summ id
				replace color_cat2 = id <= int(`share' * `r(max)')
			}

			replace category = color_cat1
			replace category = 2 if color_cat2 == 1 & category == 0


		*reverse structure for wide
			if "`wide'" != "" {
				local y x
				local x y
			}

			else {
				local y y
				local x x
			}

		*allow legends when multiple variables specified
			if "`legend'" != "" {
				local legend `legend'
				local msize = 5
			}

			else {
				local legend legend(off)
			}

		*allow msize
			if "`markersize'" != "" {
				local msize = `markersize'
			}

		*plot charts
			if "`by'" != "" {
				if "`byrows'" != "" {
					local byr = `byrows'
				}

				/*
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio')					 	///
						by(`byvar', `legend' noiyaxes noixaxes noiytick 		///
							noixtick noiylabel noixlabel note("`note'")				///
							title(`title_by')) 										///
						subtitle(, nobox) scheme(`scheme') `name')
				*/

				di as err "by() cannot be used with multiple variables. Feature will be added later. You could try plotting separately and combining."

			}

			else {
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						`legend' aspectratio(`aspectratio') title(`title_noby')	///
						scheme(`scheme') note("`note'") `name')
			}
	}

	// IF THREE VARIABLES SPECIFIED
	else if "`2'" != "" & "`3'" != "" & "`4'" == "" & "`5'" == "" {
		capture keep `1' `2' `3' `byvar' `touse'
		capture duplicates drop `1' `2' `3' `byvar' `touse', force

		*transform values to decimals if not
			if `1' > 100 | `2' > 100 | `3' > 100 {
				di as err "Variable does not appear to be a percent or decimal (it is higher than 100)"
				exit 198
			}

			if `1' > 1 {
				replace `1' = (`1' / 100)
			}

			if `2' > 1 {
				replace `2' = (`2' / 100)
			}

			if `3' > 1 {
				replace `2' = (`2' / 100)
			}

		*waffle structure
			if "`wide'" != "" {
				local rows = 20
				local cols = 5
				local aspectratio = .20
				local msize = 4
			}

			else if "`wide'" == "" {
				local rows = 10
				local cols = 10
				local aspectratio = 1
				local msize = 6
			}

		local obsv = `cols' * `rows'
		expand `obsv'

		*address issues with non-unique obs
			if "`by'" == "" & _N > 100 {
				di as err "Variable selection does not uniquely define percent. Try combining with by()"
				exit 198
			}

			/*
			duplicates report `1' `2' `byvar'
			local unique_value = `r(unique_value)'
			gen unique_val = `unique_value'
			capture levelsof `byvar'
			capture local groups = `r(r)'
			capture gen groups = `groups'
			gen error_dummy = 0
			capture replace error_dummy = 1 if unique_val > groups
			if "`by'" != "" & error_dummy == 1 {
				di as err "Variable contains too many unique values. Your by() variable levels must match the number of unique values"
				exit 198
			}
			*/

		gen seq_cat1 = `1'
		gen seq_cat2 = seq_cat1 + `2'
		gen seq_cat3 = seq_cat2 + `3'

		*by variables
			if "`by'" != "" {
				bysort `byvar' :	egen y = seq(), b(`cols')
								egen x = seq(), t(`cols')
				by `byvar' 	: 	gen id = _n
				egen tag = tag(`byvar')
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .
				local msize = 2
				levelsof `byvar', local(lvls)

				foreach x of local lvls {
					summ seq_cat1 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat1 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat2 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat2 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat3 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat3 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

			}

			else {
				egen y = seq(), b(`cols')
				egen x = seq(), t(`cols')
				gen id = _n
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .

				summ seq_cat1
				local share = `r(mean)'
				summ id
				replace color_cat1 = id <= int(`share' * `r(max)')

				summ seq_cat2
				local share = `r(mean)'
				summ id
				replace color_cat2 = id <= int(`share' * `r(max)')

				summ seq_cat3
				local share = `r(mean)'
				summ id
				replace color_cat3 = id <= int(`share' * `r(max)')
			}

			replace category = color_cat1
			replace category = 2 if color_cat2 == 1 & category == 0
			replace category = 3 if color_cat3 == 1 & category == 0


		*reverse structure for wide
			if "`wide'" != "" {
				local y x
				local x y
			}

			else {
				local y y
				local x x
			}

		*allow legends when multiple variables specified
			if "`legend'" != "" {
				local legend `legend'
				local msize = 5
			}

			else {
				local legend legend(off)
			}

		*allow msize
			if "`markersize'" != "" {
				local msize = `markersize'
			}

		*plot charts
			if "`by'" != "" {

				/*
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio')					 	///
						by(`byvar', `legend' noiyaxes noixaxes noiytick 		///
							noixtick noiylabel noixlabel note("`note'")				///
							title(`title_by')) 										///
						subtitle(, nobox) scheme(`scheme') `name')
				*/

				di as err "by() cannot be used with multiple variables. Feature will be added later. You could try plotting separately and combining."

			}

			else {
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 3, ///
							msymbol(square) mfcolor("`mcolor3'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						`legend' aspectratio(`aspectratio') title(`title_noby')	///
						scheme(`scheme') note("`note'") `name')
			}
	}

	// IF FOUR VARIABLES SPECIFIED
	else if "`2'" != "" & "`3'" != "" & "`4'" != "" & "`5'" == "" {
		capture keep `1' `2' `3' `4' `byvar' `touse'
		capture duplicates drop `1' `2' `3' `4' `byvar' `touse', force

		*transform values to decimals if not
			if `1' > 100 | `2' > 100 | `3' > 100 | `4' > 100 {
				di as err "Variable does not appear to be a percent or decimal (it is higher than 100)"
				exit 198
			}

			if `1' > 1 {
				replace `1' = (`1' / 100)
			}

			if `2' > 1 {
				replace `2' = (`2' / 100)
			}

			if `3' > 1 {
				replace `2' = (`2' / 100)
			}
			if `4' > 1 {
				replace `4' = (`4' / 100)
			}

		*waffle structure
			if "`wide'" != "" {
				local rows = 20
				local cols = 5
				local aspectratio = .20
				local msize = 4
			}

			else if "`wide'" == "" {
				local rows = 10
				local cols = 10
				local aspectratio = 1
				local msize = 6
			}

		local obsv = `cols' * `rows'
		expand `obsv'

		*address issues with non-unique obs
			if "`by'" == "" & _N > 100 {
				di as err "Variable selection does not uniquely define percent. Try combining with by()"
				exit 198
			}

			/*
			duplicates report `1' `2' `byvar'
			local unique_value = `r(unique_value)'
			gen unique_val = `unique_value'
			capture levelsof `byvar'
			capture local groups = `r(r)'
			capture gen groups = `groups'
			gen error_dummy = 0
			capture replace error_dummy = 1 if unique_val > groups
			if "`by'" != "" & error_dummy == 1 {
				di as err "Variable contains too many unique values. Your by() variable levels must match the number of unique values"
				exit 198
			}
			*/

		gen seq_cat1 = `1'
		gen seq_cat2 = seq_cat1 + `2'
		gen seq_cat3 = seq_cat2 + `3'
		gen seq_cat4 = seq_cat3 + `4'

		*by variables
			if "`by'" != "" {
				bysort `byvar' :	egen y = seq(), b(`cols')
								egen x = seq(), t(`cols')
				by `byvar' 	: 	gen id = _n
				egen tag = tag(`byvar')
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .
				gen color_cat4 = .
				local msize = 2
				levelsof `byvar', local(lvls)

				foreach x of local lvls {
					summ seq_cat1 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat1 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat2 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat2 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat3 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat3 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat4 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat4 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

			}

			else {
				egen y = seq(), b(`cols')
				egen x = seq(), t(`cols')
				gen id = _n
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .
				gen color_cat4 = .

				summ seq_cat1
				local share = `r(mean)'
				summ id
				replace color_cat1 = id <= int(`share' * `r(max)')

				summ seq_cat2
				local share = `r(mean)'
				summ id
				replace color_cat2 = id <= int(`share' * `r(max)')

				summ seq_cat3
				local share = `r(mean)'
				summ id
				replace color_cat3 = id <= int(`share' * `r(max)')

				summ seq_cat4
				local share = `r(mean)'
				summ id
				replace color_cat4 = id <= int(`share' * `r(max)')

			}

			replace category = color_cat1
			replace category = 2 if color_cat2 == 1 & category == 0
			replace category = 3 if color_cat3 == 1 & category == 0
			replace category = 4 if color_cat4 == 1 & category == 0


		*reverse structure for wide
			if "`wide'" != "" {
				local y x
				local x y
			}

			else {
				local y y
				local x x
			}

		*allow legends when multiple variables specified
			if "`legend'" != "" {
				local legend `legend'
				local msize = 5
			}

			else {
				local legend legend(off)
			}

		*allow msize
			if "`markersize'" != "" {
				local msize = `markersize'
			}

		*plot charts
			if "`by'" != "" {

				/*
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio')					 	///
						by(`byvar', `legend' noiyaxes noixaxes noiytick 		///
							noixtick noiylabel noixlabel note("`note'")				///
							title(`title_by')) 										///
						subtitle(, nobox) scheme(`scheme') `name')
				*/

				di as err "by() cannot be used with multiple variables. Feature will be added later. You could try plotting separately and combining."

			}

			else {
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 3, ///
							msymbol(square) mfcolor("`mcolor3'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 4, ///
							msymbol(square) mfcolor("`mcolor4'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						`legend' aspectratio(`aspectratio') title(`title_noby')	///
						scheme(`scheme') note("`note'") `name')
			}
	}

	// IF FIVE VARIABLES SPECIFIED
	else if "`2'" != "" & "`3'" != "" & "`4'" != "" & "`5'" != "" {
		capture keep `1' `2' `3' `4' `5' `byvar' `touse'
		capture duplicates drop `1' `2' `3' `4' `5' `byvar' `touse', force

		*transform values to decimals if not
			if `1' > 100 | `2' > 100 | `3' > 100 | `4' > 100 | `5' > 100 {
				di as err "Variable does not appear to be a percent or decimal (it is higher than 100)"
				exit 198
			}

			if `1' > 1 {
				replace `1' = (`1' / 100)
			}

			if `2' > 1 {
				replace `2' = (`2' / 100)
			}

			if `3' > 1 {
				replace `2' = (`2' / 100)
			}

			if `4' > 1 {
				replace `4' = (`4' / 100)
			}

			if `5' > 1 {
				replace `5' = (`5' / 100)
			}

		*waffle structure
			if "`wide'" != "" {
				local rows = 20
				local cols = 5
				local aspectratio = .20
				local msize = 4
			}

			else if "`wide'" == "" {
				local rows = 10
				local cols = 10
				local aspectratio = 1
				local msize = 6
			}

		local obsv = `cols' * `rows'
		expand `obsv'

		*address issues with non-unique obs
			if "`by'" == "" & _N > 100 {
				di as err "Variable selection does not uniquely define percent. Try combining with by()"
				exit 198
			}

			/*
			duplicates report `1' `2' `byvar'
			local unique_value = `r(unique_value)'
			gen unique_val = `unique_value'
			capture levelsof `byvar'
			capture local groups = `r(r)'
			capture gen groups = `groups'
			gen error_dummy = 0
			capture replace error_dummy = 1 if unique_val > groups
			if "`by'" != "" & error_dummy == 1 {
				di as err "Variable contains too many unique values. Your by() variable levels must match the number of unique values"
				exit 198
			}
			*/

		gen seq_cat1 = `1'
		gen seq_cat2 = seq_cat1 + `2'
		gen seq_cat3 = seq_cat2 + `3'
		gen seq_cat4 = seq_cat3 + `4'
		gen seq_cat5 = seq_cat4 + `5'

		*by variables
			if "`by'" != "" {
				bysort `byvar' :	egen y = seq(), b(`cols')
								egen x = seq(), t(`cols')
				by `byvar' 	: 	gen id = _n
				egen tag = tag(`byvar')
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .
				gen color_cat4 = .
				gen color_cat5 = .
				local msize = 2
				levelsof `byvar', local(lvls)

				foreach x of local lvls {
					summ seq_cat1 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat1 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat2 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat2 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat3 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat3 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat4 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat4 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}

				foreach x of local lvls {
					summ seq_cat5 if `byvar' == `x' & tag == 1
					local share = `r(mean)'
					summ id if `byvar' == `x'
					replace color_cat5 = id <= int(`share' * `r(max)') if `byvar' == `x'
				}
			}

			else {
				egen y = seq(), b(`cols')
				egen x = seq(), t(`cols')
				gen id = _n
				gen category = .
				gen color_cat1 = .
				gen color_cat2 = .
				gen color_cat3 = .
				gen color_cat4 = .
				gen color_cat5 = .

				summ seq_cat1
				local share = `r(mean)'
				summ id
				replace color_cat1 = id <= int(`share' * `r(max)')

				summ seq_cat2
				local share = `r(mean)'
				summ id
				replace color_cat2 = id <= int(`share' * `r(max)')

				summ seq_cat3
				local share = `r(mean)'
				summ id
				replace color_cat3 = id <= int(`share' * `r(max)')

				summ seq_cat4
				local share = `r(mean)'
				summ id
				replace color_cat4 = id <= int(`share' * `r(max)')

				summ seq_cat5
				local share = `r(mean)'
				summ id
				replace color_cat5 = id <= int(`share' * `r(max)')

			}

			replace category = color_cat1
			replace category = 2 if color_cat2 == 1 & category == 0
			replace category = 3 if color_cat3 == 1 & category == 0
			replace category = 4 if color_cat4 == 1 & category == 0
			replace category = 5 if color_cat5 == 1 & category == 0

		*reverse structure for wide
			if "`wide'" != "" {
				local y x
				local x y
			}

			else {
				local y y
				local x x
			}

		*allow legends when multiple variables specified
			if "`legend'" != "" {
				local legend `legend'
				local msize = 5
			}

			else {
				local legend legend(off)
			}

		*allow msize
			if "`markersize'" != "" {
				local msize = `markersize'
			}

		*plot charts
			if "`by'" != "" {

				/*
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						legend(off) aspectratio(`aspectratio')					 	///
						by(`byvar', `legend' noiyaxes noixaxes noiytick 		///
							noixtick noiylabel noixlabel note("`note'")				///
							title(`title_by')) 										///
						subtitle(, nobox) scheme(`scheme') `name')
				*/

				di as err "by() cannot be used with multiple variables. Feature will be added later. You could try plotting separately and combining."

			}

			else {
				twoway	(scatter `y' `x' if `touse' & category == 1, ///
							msymbol(square) mfcolor("`mcolor1'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 2, ///
							msymbol(square) mfcolor("`mcolor2'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 3, ///
							msymbol(square) mfcolor("`mcolor3'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 4, ///
							msymbol(square) mfcolor("`mcolor4'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 5, ///
							msymbol(square) mfcolor("`mcolor4'") ///
							mlwidth(vthin) mlcolor("`ocolor'") msize(`msize')) ///
						(scatter `y' `x' if `touse' & category == 0, ///
							msymbol(square) mfcolor("`ecolor'") ///
							mlwidth(vthin) mlcolor("`eocolor'") msize(`msize') ///
						ytitle("") yscale(noline) ylabel(, nogrid noticks nolabels) ///
						xtitle("") xscale(noline) xlabel(, nogrid noticks nolabels) ///
						`legend' aspectratio(`aspectratio') title(`title_noby')	///
						scheme(`scheme') note("`note'") `name')
			}
	}
}
restore
end