*! marimekko v1.2 (11 Nov 2024) *! Asjad Naqvi (asjadnaqvi@gmail.com) * v1.2 (11 Nov 2024): major package rework. see v1.2 rows below for the new options. * v1.1 (02 Dec 2023): Added additional options * v1.0 (28 Jun 2022): First release cap program drop marimekko program marimekko, // sortpreserve version 15 syntax varlist(min=2 max=2 numeric) [if] [in] [aw fw pw iw/], by(varname) /// [ sort(varname) reverse palette(string) LColor(string) LWidth(string) ] /// [ LABSize(string) LABAngle(string) LABGap(string) LABColor(string) LABPosition(string) ] /// [ over(varname) stat(string) xshare XPERCENTage yshare YPERCENTage legend(string) wrap(numlist max=1 >0) ] /// // v1.2 options [ LEGPOSition(real 6) LEGROWs(real 1) LEGSize(string) offset(real 0) SHOWTOTal format(string) LABCONDition(real 0) labprop labscale(real 0.3333) * ] // v1.2 options marksample touse, strok cap findfile labmask.ado if _rc != 0 quietly ssc install labutil, replace cap findfile labsplit.ado if _rc != 0 quietly ssc install graphfunctions, replace // check dependencies cap findfile colorpalette.ado if _rc != 0 { display as error "The palettes package is missing. Please install the {stata ssc install palettes, replace:palettes} and {stata ssc install colrspace, replace:colrspace} packages." exit } if "`stat'" != "" & !inlist("`stat'", "mean", "sum") { display as error "Valid options are {bf:stat(mean)} [default] or {bf:stat(sum)}." exit } if "`xshare'"!="" & "`xpercentage'"!= "" { display as error "Only one off {it:xshare} or {it:xpercent} can be specified." exit } if "`yshare'"!="" & "`ypercentage'"!= "" { display as error "Only one off {it:yshare} or {it:ypercent} can be specified." exit } quietly { preserve keep if `touse' tokenize `varlist' gen double _yvar = `1' gen double _xvar = `2' local xvar _xvar local yvar _yvar keep `xvar' `yvar' `by' `over' `exp' `sort' drop if missing(`by') drop if missing(`over') if "`over'"=="" { gen _over = 1 local over _over local ovrskip 1 } else { local ovrskip 0 } if "`sort'" == "" { bysort `by': egen _mysort = sum(`xvar') } else { gen _mysort = `sort' } local sort _mysort if "`stat'" == "" local stat sum if "`weight'" != "" local myweight [`weight' = `exp'] collapse (`stat') `xvar' `yvar' (mean) `sort' `myweight' , by(`by' `over') sort `by' `over' *by `by': egen _sort = sum(`sort') by `by': gen double _ysum = sum(`yvar') by `by': egen double _xtotal = sum(`xvar') by `by': egen double _ytotal = sum(`yvar') if "`sort'" != "" { if "`reverse'" != "" { sort `sort' } else { gsort -`sort' } } // deal with the variable type gen id = _n // x categories egen _grp1 = tag(`by') replace _grp1 = sum(_grp1) cap confirm numeric var `by' if _rc!=0 { labmask _grp1, val(`by') } else { decode `by', gen(_name) labmask _grp1, val(_name) drop _name } // y categories egen _grp2 = group(`over') cap confirm numeric var `over' if _rc!=0 { // if string labmask _grp2, values(`over') } else { // if numeric if "`: value label `over''" != "" { // with value label decode `over', gen(_name) labmask _grp2, val(_name) drop _name } } sort `sort' `by' `over' // rectangles tempvar xe xs ye ys levelsof _grp1, local(lvls) gen double _xs = . gen double _xe = . local xstart = 0 local xend = 0 foreach x of local lvls { local xstart = `xend' summ _xvar if _grp1==`x', meanonly local xend = `r(sum)' + `xend' replace _xs = `xstart' if _grp1==`x' replace _xe = `xend' if _grp1==`x' } gen double _ye = _ysum gen double _ys = _ye[_n-1] replace _ys = 0 if _grp2==1 // share or percentage if "`yshare'" != "" { replace _ys = _ys / _ytotal replace _ye = _ye / _ytotal } if "`ypercentage'" != "" { replace _ys = (_ys / _ytotal) * 100 replace _ye = (_ye / _ytotal) * 100 } if "`xshare'" != "" { summ _xe, meanonly replace _xs = _xs / `r(max)' replace _xe = _xe / `r(max)' } if "`xpercentage'" != "" { summ _xe, meanonly replace _xs = (_xs / `r(max)') * 100 replace _xe = (_xe / `r(max)') * 100 } levelsof _grp2, local(lvl2) foreach x of local lvl2 { count if _grp2==`x' local targetobs = `r(N)' * 6 if _N < `targetobs' set obs `targetobs' gen int _id`x' = . gen double _x`x' = . gen double _y`x' = . levelsof _grp1 if _grp2==`x', local(lvl1) foreach y of local lvl1 { local i = (`y'- 1) * 6 replace _id`x' = `y' in `=`i'+1'/`=`i'+6' // x summ _xs if _grp2==`x' & _grp1==`y', meanonly replace _x`x' = r(mean) in `=`i'+1' replace _x`x' = r(mean) in `=`i'+2' replace _x`x' = r(mean) in `=`i'+5' summ _xe if _grp2==`x' & _grp1==`y', meanonly replace _x`x' = r(mean) in `=`i'+3' replace _x`x' = r(mean) in `=`i'+4' // y summ _ys if _grp2==`x' & _grp1==`y', meanonly replace _y`x' = r(mean) in `=`i'+1' replace _y`x' = r(mean) in `=`i'+4' replace _y`x' = r(mean) in `=`i'+5' summ _ye if _grp2==`x' & _grp1==`y', meanonly replace _y`x' = r(mean) in `=`i'+2' replace _y`x' = r(mean) in `=`i'+3' } } // fix labels levelsof _grp1, local(lvls) gen double _labx = . gen double _laby = . gen double _labval = . gen _labname = "" local x0 = 0 foreach x of local lvls { // y summ _ye if _grp1==`x', meanonly replace _laby = r(max) * (1 + (`offset' / 100)) in `x' // x summ _xe if _grp1==`x', meanonly local x1 = r(max) replace _labx = (`x0' + `x1') / 2 in `x' local x0 = `x1' // value summ _xtotal if _grp1==`x', meanonly replace _labval = r(max) in `x' // label local t : label _grp1 `x' replace _labname = "`t'" in `x' } *** define format options if "`format'" == "" { if "`shares'"!="" | "`percent'"!="" { local format "%4.2f" } else { local format "%12.2fc" } } if "`showtotal'" !="" { if "`xshare'" != "" { summ _labval, meanonly replace _labval = _labval / r(sum) replace _labname = _labname + " (" + string(_labval, "`format'") + ")" if !missing(_labname) } else if "`xpercentage'"!= "" { summ _labval, meanonly replace _labval = (_labval / r(sum)) * 100 replace _labname = _labname + " (" + string(_labval, "`format'") + "%)" if !missing(_labname) } else { replace _labname = _labname + " (" + string(_labval, "`format'") + ")" if !missing(_labname) } } replace _labname = "" if _labval < `labcondition' if "`wrap'" != "" { ren _labname _labname_old labsplit _labname_old, wrap(`wrap') gen(_labname) drop _labname_old } // locals here if "`lwidth'" == "" local lwidth 0.1 if "`lcolor'" == "" local lcolor white if "`palette'" == "" { local palette tableau } else { tokenize "`palette'", p(",") local palette `1' local poptions `3' } // draw here if "`labgap'" == "" local labgap 0 if "`labsize'" == "" local labsize 2 if "`labangle'" == "" local labangle 0 if "`labcolor'" == "" local labcolor black if "`labposition'" == "" local labposition 12 if "`labprop'"== "" { local labels (scatter _laby _labx, mlab(_labname) mc(none) mlabangle(`labangle') mlabposition(`labposition') mlabcolor(`labcolor') mlabsize(`labsize')) } levelsof _grp2, local(lvls) local items = r(r) foreach x of local lvls { colorpalette `palette', nograph `poptions' // n(`items') local bars `bars' (area _y`x' _x`x', cmissing(n) nodropbase fc("`r(p`x')'") fi(100) lc(`lcolor') lw(`lwidth')) } if "`labprop'"== "" { local labels (scatter _laby _labx, mlab(_labname) mc(none) mlabangle(`labangle') mlabposition(`labposition') mlabcolor(`labcolor') mlabsize(`labsize')) } else { summ _labval, meanonly local height = r(sum) levelsof _grp1, local(lvls) foreach x of local lvls { summ _labval in `x' , meanonly local labwgt = `labsize' * (r(max) / `height')^`labscale' local labels `labels' (scatter _laby _labx in `x', mlab(_labname) mc(none) mlabangle(`labangle') mlabposition(`labposition') mlabcolor(`labcolor') mlabsize(`labwgt')) } } // fix legend if "`legsize'" == "" local legsize 2.5 if `ovrskip' == 1 { // skip legend if no over defined. local legend legend(off) } else { if "`legend'" == "" { levelsof _grp2, local(lvls) foreach x of local lvls { local t : label _grp2 `x' lab var _y`x' "`t'" local entries `" `entries' `x' "`t'" "' } local legend legend(order("`entries'") position(`legposition') size(`legsize') rows(`legrows')) } } // put it together twoway /// `bars' /// `labels' /// , /// `legend' `options' */ restore } end ********************************* ******** END OF PROGRAM ********* *********************************