├── .github └── FUNDING.yml ├── data ├── streamdata.dta └── wbgdpdata.dta ├── figures ├── streamplot1.png ├── streamplot2.png ├── streamplot2_1.png ├── streamplot2_2.png ├── streamplot3.png ├── streamplot3_1.png ├── streamplot3_2.png ├── streamplot3_3.png ├── streamplot3_4.png ├── streamplot4.png ├── streamplot5.png ├── streamplot6.png ├── streamplot7.png ├── streamplot8.png ├── streamplot_tline1.png ├── streamplot_tline2.png ├── streamplot_tline3.png ├── streamplot_tline4.png ├── streamplot_tline5.png ├── streamplot_tline6.png ├── streamplot_tline7.png ├── streamplot_labprop1.png ├── streamplot_labprop2.png ├── streamplot_labprop3.png └── streamplot_labprop4.png ├── CITATION.cff ├── installation ├── stata.toc ├── streamplot.pkg ├── streamplot.sthlp └── streamplot.ado ├── LICENSE └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: asjadnaqvi 2 | -------------------------------------------------------------------------------- /data/streamdata.dta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/data/streamdata.dta -------------------------------------------------------------------------------- /data/wbgdpdata.dta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/data/wbgdpdata.dta -------------------------------------------------------------------------------- /figures/streamplot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot1.png -------------------------------------------------------------------------------- /figures/streamplot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot2.png -------------------------------------------------------------------------------- /figures/streamplot2_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot2_1.png -------------------------------------------------------------------------------- /figures/streamplot2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot2_2.png -------------------------------------------------------------------------------- /figures/streamplot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot3.png -------------------------------------------------------------------------------- /figures/streamplot3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot3_1.png -------------------------------------------------------------------------------- /figures/streamplot3_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot3_2.png -------------------------------------------------------------------------------- /figures/streamplot3_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot3_3.png -------------------------------------------------------------------------------- /figures/streamplot3_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot3_4.png -------------------------------------------------------------------------------- /figures/streamplot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot4.png -------------------------------------------------------------------------------- /figures/streamplot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot5.png -------------------------------------------------------------------------------- /figures/streamplot6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot6.png -------------------------------------------------------------------------------- /figures/streamplot7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot7.png -------------------------------------------------------------------------------- /figures/streamplot8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot8.png -------------------------------------------------------------------------------- /figures/streamplot_tline1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline1.png -------------------------------------------------------------------------------- /figures/streamplot_tline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline2.png -------------------------------------------------------------------------------- /figures/streamplot_tline3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline3.png -------------------------------------------------------------------------------- /figures/streamplot_tline4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline4.png -------------------------------------------------------------------------------- /figures/streamplot_tline5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline5.png -------------------------------------------------------------------------------- /figures/streamplot_tline6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline6.png -------------------------------------------------------------------------------- /figures/streamplot_tline7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_tline7.png -------------------------------------------------------------------------------- /figures/streamplot_labprop1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_labprop1.png -------------------------------------------------------------------------------- /figures/streamplot_labprop2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_labprop2.png -------------------------------------------------------------------------------- /figures/streamplot_labprop3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_labprop3.png -------------------------------------------------------------------------------- /figures/streamplot_labprop4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/HEAD/figures/streamplot_labprop4.png -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | authors: 3 | - family-names: "Naqvi" 4 | given-names: "Asjad" 5 | title: "Stata package ``streamplot''" 6 | version: 1.9 7 | date-released: 2025-02-08 8 | url: "https://github.com/asjadnaqvi/stata-streamplot" 9 | -------------------------------------------------------------------------------- /installation/stata.toc: -------------------------------------------------------------------------------- 1 | v 1.9 2 | d STREAMPLOT: A package for creating stream plots in Stata 3 | d 4 | d Asjad Naqvi 5 | d asjadnaqvi@gmail.com 6 | d 7 | d Distribution-Date: 20250208 8 | d 9 | d https://medium.com/the-stata-guide 10 | d https://github.com/asjadnaqvi/Stata-schemes 11 | 12 | -------------------------------------------------------------------------------- /installation/streamplot.pkg: -------------------------------------------------------------------------------- 1 | v 1.9 2 | d {bf:STREAMPLOT}: A package for creating streamplots in Stata 3 | d 4 | d Requires: Stata version 15 or higher. 5 | d 6 | d KW: Stata 7 | d KW: graphs 8 | d KW: streamplot 9 | d 10 | d Distribution-Date: 20250208 11 | d 12 | d This version: 08 Feb 2025 13 | d First version: 05 Dec 2021 14 | d License: MIT 15 | d 16 | d Author: Asjad Naqvi (asjadnaqvi@gmail.com) 17 | d 18 | f streamplot.ado 19 | f streamplot.sthlp 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Asjad Naqvi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /installation/streamplot.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 08Feb2025}{...} 3 | {hi:help streamplot}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-streamplot":streamplot v1.9 (GitHub)}} 5 | 6 | {hline} 7 | 8 | {title:streamplot}: A Stata package for stream plots. 9 | 10 | {p 4 4 2} 11 | The command is based on the following guide on Medium: {browse "https://medium.com/the-stata-guide/covid-19-visualizations-with-stata-part-10-stream-graphs-9d55db12318a":Stream plots}. 12 | 13 | 14 | {marker syntax}{title:Syntax} 15 | {p 8 15 2} 16 | 17 | {cmd:streamplot} {it:y x} {ifin}, {cmd:by}(varname) 18 | {cmd:[} {cmd:palette}({it:str}) {cmd:smooth}({it:num}) {cmd:labcond}({it:str}) {cmd:offset}({it:num}) {cmd:alpha}({it:num}) {cmdab:yrev:erse} {cmd:cat}({it:varname}) 19 | {cmdab:rec:enter}({it:top}|{it:mid}|{it:bot}) {cmdab:lc:olor}({it:str}) {cmdab:lw:idth}({it:str}) {cmdab:labs:ize}({it:num}) {cmdab:labc:olor}({it:color}|{it:palette}) 20 | {cmd:percent} {cmd:format}({it:str}) {cmdab:area} {cmdab:nolab:el} {cmd:wrap}({it:num}) {cmd:tline} {cmdab:tlc:olor}({it:str}) {cmdab:tlw:idth}({it:str}) 21 | {cmdab:tlp:attern}({it:str}) {cmd:yline}({it:str}) {cmdab:laboff:set}({it:num}) {cmd:labprop} {cmd:labscale}({it:num}) {cmd:wrap}({it:num}) {cmd:*} 22 | {cmd:]} 23 | 24 | 25 | {p 4 4 2} 26 | The options are described as follows: 27 | 28 | {synoptset 36 tabbed}{...} 29 | {synopthdr} 30 | {synoptline} 31 | 32 | {p2coldent : {opt streamplot y x}}The command requires a numeric {it:y} variable and a numeric {it:x} variable. The x variable is usually a time variable.{p_end} 33 | 34 | {p2coldent : {opt by(var)}}This is the group variable that defines the layers.{p_end} 35 | 36 | {p2coldent : {opt cat(var)}}This is a binary variable that defines the split above and below the y=0 axis. Useful for comparise {opt by()} variables across two categories. 37 | Note that defining {opt cat()} overwrites the {opt recenter()} option explained below.{p_end} 38 | 39 | {p2coldent : {opt rec:enter(top|mid|bot)}}This option changes where the graph is recentered. The default option is {opt rec:enter(middle)}. 40 | Additional options are {opt rec:enter(top)} or {opt rec:enter(bottom)}. 41 | For brevity, the following can be specified: {it:middle} = {it:mid} = {it:m}, {it:top} = {it:t}, {it:bottom} = {it:bot} = {it:b}.{p_end} 42 | 43 | {p2coldent : {opt yrev:erse}}Reverse the variable labels.{p_end} 44 | 45 | {p2coldent : {opt nolab:el}}Hide the variable labels.{p_end} 46 | 47 | {p2coldent : {opt area}}Show stacked area graph. Options {opt recenter(bottom)} and {opt smooth(0)} are recommended with this option.{p_end} 48 | 49 | {p2coldent : {opt smooth(num)}}The smoothing parameter defined in terms of last observations to use. The default value is {opt smooth(3)}. 50 | A value of 0 implies no smoothing.{p_end} 51 | 52 | {p2coldent : {opt palette(str)}}Color name is any named scheme defined in the {stata help colorpalette:colorpalette} package. 53 | Default is {stata colorpalette tableau:{it:tableau}}.{p_end} 54 | 55 | {p2coldent : {opt alpha(num)}}The transparency of area fills. The default value is {opt alpha(100)}. It is better to leave this option as it is.{p_end} 56 | 57 | {p2coldent : {opt offset(num)}}Extends the x-axis range to accommodate labels. The default value is {opt offset(15)} for 15% of {it:xmax-xmin} of the axis range.{p_end} 58 | 59 | {p2coldent : {opt wrap(num)}}Wrap the labels after a specific number of characters. Word boundaries are respected. Requires the latest {stata help graphfunctions:graphfunctions} package.{p_end} 60 | 61 | {p2coldent : {opt labc:olor(str)}}Label colors are either defined as a single color, e.g. default is {opt labc(black)}. Or if {opt labc(palette)} is specified, 62 | labels have the {opt palette()} colors.{p_end} 63 | 64 | {p2coldent : {opt labs:ize(str)}}Size of the stream labels. The default value is {opt labs(1.4)}.{p_end} 65 | 66 | {p2coldent : {opt percent}}Shows the percentage share for the y-axis categories.{p_end} 67 | 68 | {p2coldent : {opt format(fmt)}}Format the values of the y-axis category. The default is {opt format(%12.0f)}.{p_end} 69 | 70 | {p2coldent : {opt laboff:set(num)}}Offset the stream labels. Negative values will offset towards the left. The default is {opt laboff(0)}.{p_end} 71 | 72 | {p2coldent : {opt labcond(num)}}The label condition can be used to limit the number of labels shown. 73 | For example, {opt labcond(100)} will only shows labels where the last data point value is greater than 100.{p_end} 74 | 75 | {p2coldent : {opt lw:idth(str)}}The line width of the area stroke. The default is {opt lw(0.05)}.{p_end} 76 | 77 | {p2coldent : {opt lc:olor(str)}}The line color of the area stroke. The default is {opt lc(white)}.{p_end} 78 | 79 | {p2coldent : {opt tline}}Add a timeline which is the running sum of all the layers. Helpful for showing aggregates if {opt cat()} is used.{p_end} 80 | 81 | {p2coldent : {opt tlw:idth(str)}}The timeline width. The default is {opt tlw(0.3)}.{p_end} 82 | 83 | {p2coldent : {opt tlc:olor(str)}}The timeline color. The default is {opt tlc(black)}.{p_end} 84 | 85 | {p2coldent : {opt tlp:attern(str)}}The timeline pattern. The default is {opt tlp(solid)}.{p_end} 86 | 87 | {p2coldent : {opt labprop}}Scale the bar labels based on the relative values.{p_end} 88 | 89 | {p2coldent : {opt labscale(num)}}Scale factor of {opt labprop}. Default value is {opt labscale(0.3333)}. Values closer to zero result in more exponential scaling, while values closer 90 | to one are almost linear scaling. This is an advanced option so use carefully.{p_end} 91 | 92 | {p2coldent : {opt *}}All other standard twoway options.{p_end} 93 | 94 | {hline} 95 | 96 | {title:Dependencies} 97 | 98 | {stata ssc install palettes, replace} 99 | {stata ssc install colrspace, replace} 100 | {stata ssc install graphfunctions, replace} 101 | 102 | 103 | {title:Examples} 104 | 105 | See {browse "https://github.com/asjadnaqvi/stata-streamplot":GitHub}. 106 | 107 | 108 | {title:Feedback} 109 | 110 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-streamplot/issues":GitHub} by opening a new issue. 111 | 112 | 113 | {title:Citation guidelines} 114 | 115 | See {browse "https://ideas.repec.org/c/boc/bocode/s459060.html"} for the official SSC citation. 116 | Please note that the GitHub version might be newer than the SSC version. 117 | 118 | 119 | {title:Package details} 120 | 121 | Version : 1.9 122 | This release : 08 Feb 2025 123 | First release: 06 Aug 2021 124 | Repository : {browse "https://github.com/asjadnaqvi/stata-streamplot":GitHub} 125 | Keywords : Stata, graph, streamplot 126 | License : {browse "https://opensource.org/licenses/MIT":MIT} 127 | 128 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 129 | E-mail : asjadnaqvi@gmail.com 130 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 131 | BlueSky : {browse "https://bsky.app/profile/asjadnaqvi.bsky.social":@asjadnaqvi.bsky.social} 132 | 133 | 134 | {title:References} 135 | 136 | {p 4 8 2}Jann, B. (2018). {browse "https://www.stata-journal.com/article.html?article=gr0075":Color palettes for Stata graphics}. The Stata Journal 18(4): 765-785. 137 | 138 | {p 4 8 2}Jann, B. (2022). {browse "https://ideas.repec.org/p/bss/wpaper/43.html":Color palettes for Stata graphics: An update}. University of Bern Social Sciences Working Papers No. 43. 139 | 140 | 141 | {title:Other visualization packages} 142 | {psee} 143 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb geoboundary}, {helpb geoflow}, {helpb joyplot}, 144 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 145 | 146 | Visit {browse "https://github.com/asjadnaqvi":GitHub} for further information. -------------------------------------------------------------------------------- /installation/streamplot.ado: -------------------------------------------------------------------------------- 1 | *! streamplot v1.9 (08 Feb 2025) 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | * v1.9 (08 Feb 2025): droplow taken out. all categories will now draw. label wrapping improved. more checks added. Added laboffset 5 | * v1.82 (10 Jun 2024): add wrap() for label wraps. 6 | * v1.81 (30 Apr 2024): added area option to create stacked area plots. 7 | * v1.8 (25 Apr 2024): added labscale option. Added percent/share as substitutes. more flexible for generic options. 8 | * v1.7 (01 Apr 2024): trendline, yline, drop if by() is missing 9 | * v1.61 (15 Jan 2024): fixed wrong locals. changed ylab to just lab. 10 | * v1.6 (15 Oct 2023): cat() option added. yrev, labcond() fixed. major code cleanup. 11 | * v1.52 (25 Aug 2023): Support for aspect(), saving(), nolabel, nodraw, xscale() and graphregion() added. 12 | * v1.51 (28 May 2023): Clean up labcond and offset changes to percentages. 13 | * v1.5 (20 Nov 2022): recenter option added. improved variable precision. 14 | * v1.4 (08 Nov 2022): Major code cleanup and some parts reworked. Observation checks. Palette options. label controls. 15 | * v1.3 (20 Jun 2022): Add marker labels and format options 16 | * v1.2 (14 Jun 2022): passthru optimizations. error checks. reduce the default smoothing. labels fix 17 | * v1.1 (08 Apr 2022): First release 18 | * v1.0 (06 Aug 2021): Beta version 19 | 20 | 21 | 22 | cap program drop streamplot 23 | 24 | program streamplot, sortpreserve 25 | 26 | version 15 27 | 28 | syntax varlist(min=2 max=2 numeric) [if] [in], by(varname) /// 29 | [ palette(string) alpha(real 100) smooth(real 3) LColor(string) LWidth(string) labcond(real 0) ] /// 30 | [ LABSize(string) LABColor(string) offset(real 15) format(string) RECenter(string) ] /// 31 | [ NOLABel cat(varname) YREVerse ] /// // v1.5x v1.6 32 | [ tline TLColor(string) TLWidth(string) TLPattern(string) ] /// // v1.7 33 | [ * labprop labscale(real 0.3333) percent share area wrap(numlist >=0 max=1) LABOFFset(real 0) ] // 1.8 options 34 | 35 | 36 | // check dependencies 37 | cap findfile colorpalette.ado 38 | if _rc != 0 { 39 | 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." 40 | exit 41 | } 42 | 43 | cap findfile labmask.ado 44 | if _rc != 0 quietly ssc install labutil, replace 45 | 46 | cap findfile labsplit.ado 47 | if _rc != 0 quietly ssc install graphfunctions, replace 48 | 49 | 50 | 51 | marksample touse, strok 52 | gettoken yvar xvar : varlist 53 | 54 | if "`cat'"!= "" { 55 | quietly levelsof `cat' 56 | if r(r) > 2 { 57 | di as error "`cat' in cat() is not a binary variable." 58 | exit 198 59 | } 60 | } 61 | 62 | 63 | 64 | quietly { 65 | preserve 66 | 67 | keep if `touse' 68 | 69 | drop if missing(`by') 70 | 71 | if "`cat'"=="" { 72 | gen _cat = 1 // run a dummy 73 | local cat _cat 74 | local rebasecat 0 75 | } 76 | else { 77 | local rebasecat 1 78 | } 79 | 80 | collapse (sum) `yvar', by(`xvar' `by' `cat') 81 | 82 | fillin `by' `xvar' 83 | 84 | replace `yvar' = 0 if `yvar' < 0 // this is technically wrong but we do it anyways 85 | recode `yvar' (.=0) 86 | 87 | sort `by' `cat' `xvar' 88 | bysort `by': replace `cat' = `cat'[1] if `cat'==. 89 | cap drop _fillin 90 | 91 | 92 | egen _order = group(`cat' `by') // this is the primary order category 93 | 94 | 95 | cap confirm numeric var `by' 96 | if !_rc { // if numeric 97 | if "`: value label `by''" != "" { // with val labels 98 | tempvar tempov 99 | decode `by', gen(`tempov') 100 | cap labmask _order, val(`tempov') 101 | lab val _order _order 102 | } 103 | else { // without val labels 104 | tempvar tempov 105 | encode `by', gen(`tempov') 106 | cap labmask _order, val(`by') 107 | lab val _order _order 108 | } 109 | } 110 | else { // if string 111 | label list 112 | cap labmask _order, val(`by') 113 | lab val _order _order 114 | } 115 | 116 | 117 | 118 | local by _order 119 | 120 | 121 | if "`yreverse'" != "" { 122 | 123 | clonevar over2 = `by' 124 | 125 | summ `by', meanonly 126 | replace `by' = r(max) - `by' + 1 127 | 128 | if "`: value label over2'" != "" { 129 | tempvar group2 130 | decode over2, gen(`group2') 131 | replace `group2' = string(over2) if `group2'=="" 132 | labmask `by', val(`group2') 133 | } 134 | else { 135 | labmask `by', val(over2) 136 | } 137 | } 138 | 139 | 140 | keep `xvar' `cat' `by' `yvar' 141 | order `xvar' `cat' `by' `yvar' 142 | 143 | xtset `by' `xvar' 144 | 145 | if "`area'" != "" { 146 | bysort `xvar': egen double _sum = sum(`yvar') 147 | replace `yvar' = (`yvar' / _sum) * 100 148 | drop _sum 149 | } 150 | 151 | 152 | tssmooth ma _ma = `yvar' , w(`smooth' 1 0) 153 | 154 | // add the range variable on the x-axis 155 | 156 | if "`nolabel'"!="" local offset 0 // reset to 0 157 | 158 | summ `xvar' if _ma != ., meanonly 159 | local xrmin = r(min) 160 | local xrmax = r(max) + ((r(max) - r(min)) * (`offset' / 100)) 161 | 162 | 163 | sort `xvar' `by' // extremely important for stack order. 164 | by `xvar': gen double _stack = sum(_ma) 165 | 166 | if `rebasecat' == 1 { 167 | egen _temp = group(`cat') 168 | gen _nsval = _ma * (_temp==2) + -_ma * (_temp==1) 169 | by `xvar': egen double _linevar = sum(_nsval) 170 | } 171 | else { 172 | bysort `xvar': egen double _linevar = max(_stack) 173 | } 174 | 175 | 176 | ** preserve the labels for use later 177 | 178 | local mylab: value label `by' 179 | 180 | levelsof `by', local(idlabels) // store the id levels 181 | 182 | foreach x of local idlabels { 183 | local idlab_`x' : label `mylab' `x' // store the corresponding value label in a macro 184 | 185 | } 186 | 187 | 188 | if "`yreverse'" == "" { 189 | summ `cat' 190 | summ _order if `cat'==r(max) 191 | local rebase = r(min) - 1 // if cat is defined, store the rebase index 192 | } 193 | else { 194 | summ `cat' 195 | summ _order if `cat'==r(max) 196 | local rebase = r(max) 197 | } 198 | 199 | summ _order, meanonly 200 | local lastval = r(max) 201 | 202 | 203 | ren `yvar' _yvar 204 | 205 | cap drop `cat' _temp _nsval 206 | 207 | reshape wide _stack _yvar _ma , i(`xvar' _linevar) j(`by') 208 | 209 | foreach x of local idlabels { // here we know how many variables we have 210 | 211 | lab var _stack`x' "`idlab_`x''" 212 | lab var _ma`x' "`idlab_`x''" 213 | lab var _yvar`x' "`idlab_`x''" 214 | } 215 | 216 | 217 | gen _stack0 = 0 // we need this for area graphs 218 | 219 | 220 | order `xvar' _stack0 221 | 222 | 223 | if `rebasecat' == 0 { 224 | ds _ma* 225 | local items : word count `r(varlist)' 226 | local items = `items' - 1 227 | 228 | if "`recenter'" == "" | "`recenter'"=="middle" | "`recenter'"=="mid" | "`recenter'"=="m" { 229 | gen double _meanval = _stack`items' / 2 230 | } 231 | 232 | if "`recenter'" == "bottom" | "`recenter'"=="bot" | "`recenter'"=="b" { 233 | gen _meanval = 0 234 | } 235 | 236 | if "`recenter'" == "top" | "`recenter'"=="t" { 237 | local items2 = `items' + 1 238 | gen double _meanval = _stack`items2' 239 | } 240 | } 241 | else { 242 | gen double _meanval = _stack`rebase' 243 | } 244 | 245 | 246 | if "`area'" != "" { // overwrite 247 | cap drop _meanval 248 | gen _meanval = 0 249 | } 250 | 251 | 252 | foreach x of varlist _stack* { 253 | gen double `x'_norm = `x' - _meanval 254 | } 255 | 256 | if `rebasecat' == 0 replace _linevar = _linevar - _meanval 257 | 258 | // this part is for the mid points 259 | 260 | gen double _ylab = . 261 | gen double _yval = . 262 | gen double _yshare = . 263 | gen _yname = "" 264 | 265 | ds _stack*_norm 266 | local items : word count `r(varlist)' 267 | local items = `items' - 2 268 | 269 | local counter = 1 270 | 271 | forval i = 0/`items' { 272 | local i0 = `i' 273 | local i1 = `i' + 1 274 | local t : var lab _ma`i1' 275 | 276 | replace _ylab = (_stack`i0'_norm[_N] + _stack`i1'_norm[_N]) / 2 in `counter' 277 | replace _yval = _yvar`i1'[_N] in `counter' 278 | replace _yname = "`t'" in `counter' 279 | 280 | local ++counter 281 | } 282 | 283 | sum _yval, meanonly 284 | replace _yshare = (_yval / `r(sum)') * 100 285 | 286 | summ `xvar', meanonly 287 | gen _xlab = r(max) + `laboffset' if _yval!=. 288 | 289 | **** automate this part 290 | 291 | 292 | ds _stack*norm 293 | local items : word count `r(varlist)' 294 | local items = `items' - 1 295 | 296 | 297 | if "`format'" == "" { 298 | if "`percent'"=="" & "`share'"=="" & "`area'"=="" { 299 | local format %15.0fc 300 | } 301 | else { 302 | local format %6.1f 303 | } 304 | } 305 | 306 | 307 | if "`percent'" != "" | "`share'"!="" { 308 | gen _label = _yname + " (" + string(_yshare, "`format'") + "%)" if _yval>0 & !missing(_yval) 309 | } 310 | else { 311 | gen _label = _yname + " (" + string(_yval, "`format'") + ")" if _yval>0 & !missing(_yval) //if last==1 & `labvar' >= `labcond' 312 | } 313 | 314 | 315 | if "`wrap'" != "" { 316 | ren _label _label2 317 | labsplit _label2, wrap(`wrap') gen(_label) 318 | } 319 | 320 | 321 | if "`labsize'" == "" local labsize 1.6 322 | if "`lcolor'" == "" local lcolor white 323 | if "`lwidth'" == "" local lwidth 0.05 324 | if "`labcolor'" != "palette" local ycolor `labcolor' 325 | if "`palette'" == "" { 326 | local palette tableau 327 | } 328 | else { 329 | tokenize "`palette'", p(",") 330 | local palette `1' 331 | local poptions `3' 332 | } 333 | 334 | 335 | summ _stack0_norm, meanonly 336 | 337 | if "`recenter'" == "" | "`recenter'" == "middle" | "`recenter'" == "mid" | "`recenter'" == "m" { 338 | 339 | local ymin = -1 * abs(r(min)) * 1.05 340 | local ymax = abs(r(min)) * 1.05 341 | } 342 | 343 | if "`recenter'" == "bottom" | "`recenter'" == "bot" | "`recenter'" == "b" { 344 | 345 | local ymin = 0 346 | local ymax = abs(r(min)) * 1.05 347 | } 348 | 349 | if "`recenter'" == "top" | "`recenter'" == "t" { 350 | 351 | local ymin = -1 * abs(r(min)) * 1.05 352 | local ymax = 0 353 | } 354 | 355 | 356 | if "`cat'" != "" { 357 | summ _stack0_norm, meanonly 358 | local ymin = -1 * abs(r(min)) * 1.05 359 | 360 | summ _stack`items'_norm, meanonly 361 | local ymax = 1 * abs(r(max)) * 1.05 362 | } 363 | 364 | 365 | if "`tline'" != "" { 366 | if "`tlcolor'" == "" local tlcolor black 367 | if "`tlwidth'" == "" local tlwidth 0.3 368 | if "`tlpattern'" == "" local tlpattern solid 369 | 370 | local trendline (line _linevar `xvar', lc(`tlcolor') lw(`tlwidth') lp(`tlpattern')) 371 | } 372 | 373 | 374 | 375 | if "`nolabel'"=="" & "`labprop'" == "" & "`labcolor'" !="palette" { 376 | local labels `labels' (scatter _ylab _xlab if _yval >= `labcond' , mlabel(_label) mcolor(none) mlabsize(`labsize') mlabcolor("`labcolor'")) 377 | } 378 | 379 | 380 | summ _yval, meanonly 381 | local height = r(max) 382 | 383 | 384 | ds _stack*norm 385 | local items : word count `r(varlist)' 386 | local items = `items' - 2 387 | 388 | local counter = 1 389 | 390 | forval x = 0/`items' { 391 | 392 | local numcolor = `items' + 1 393 | 394 | colorpalette `palette', n(`numcolor') nograph `poptions' 395 | 396 | local x0 = `x' 397 | local x1 = `x' + 1 398 | 399 | local areagraph `areagraph' rarea _stack`x0'_norm _stack`x1'_norm `xvar', fcolor("`r(p`x1')'") fi(100) lcolor(`lcolor') lwidth(`lwidth') || 400 | 401 | 402 | if "`labcolor'" == "palette" { 403 | local ycolor "`r(p`x1')'" 404 | } 405 | 406 | 407 | if "`nolabel'"=="" { 408 | if "`labprop'" != "" { 409 | summ _yval in `counter' , meanonly 410 | local labwgt = `labsize' * (r(max) / `height')^`labscale' 411 | 412 | local labels `labels' (scatter _ylab _xlab in `counter' if _yval >= `labcond' , mlabel(_label) mcolor(none) mlabsize(`labwgt') mlabcolor("`ycolor'")) 413 | local ++counter 414 | } 415 | 416 | 417 | if "`labprop'"=="" & "`labcolor'"=="palette" { 418 | 419 | local labels `labels' (scatter _ylab _xlab in `counter' if _yval >= `labcond', mlabel(_label) mcolor(none) mlabsize(`labsize') mlabcolor("`ycolor'")) 420 | local ++counter 421 | } 422 | } 423 | } 424 | 425 | 426 | 427 | *** final graph 428 | 429 | twoway /// 430 | `areagraph' /// 431 | `labels' /// 432 | `trendline' /// 433 | , /// 434 | legend(off) /// 435 | yscale(noline) /// 436 | ylabel(`ymin' `ymax', nolabels noticks nogrid) /// 437 | xscale(noline range(`xrmin' `xrmax')) /// 438 | `options' 439 | 440 | */ 441 | 442 | restore 443 | } 444 | 445 | end 446 | 447 | 448 | 449 | ********************************* 450 | ******** END OF PROGRAM ********* 451 | ********************************* 452 | 453 | 454 | 455 | 456 | 457 | 458 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ![StataMin](https://img.shields.io/badge/stata-2015-blue) ![issues](https://img.shields.io/github/issues/asjadnaqvi/stata-streamplot) ![license](https://img.shields.io/github/license/asjadnaqvi/stata-streamplot) ![Stars](https://img.shields.io/github/stars/asjadnaqvi/stata-streamplot) ![version](https://img.shields.io/github/v/release/asjadnaqvi/stata-streamplot) ![release](https://img.shields.io/github/release-date/asjadnaqvi/stata-streamplot) 4 | 5 | 6 | [Installation](#Installation) | [Syntax](#Syntax) | [Citation guidelines](#Citation-guidelines) | [Examples](#Examples) | [Feedback](#Feedback) | [Change log](#Change-log) 7 | 8 | --- 9 | 10 | 11 | ![streamplot](https://github.com/asjadnaqvi/stata-streamplot/assets/38498046/4b7bbaab-8667-4f47-a119-ec93dcd607a3) 12 | 13 | 14 | # streamplot v1.9 15 | (08 Feb 2024) 16 | 17 | This package provides the ability to generate stream plots in Stata. It is based on the [Streamplot Guide](https://medium.com/the-stata-guide/covid-19-visualizations-with-stata-part-10-stream-graphs-9d55db12318a) (December 2020). 18 | 19 | 20 | ## Installation 21 | 22 | The package can be installed via SSC or GitHub. The GitHub version, *might* be more recent due to bug fixes, feature updates etc, and *may* contain syntax improvements and changes in *default* values. See version numbers below. Eventually the GitHub version is published on SSC. 23 | 24 | SSC (**v1.9**): 25 | ``` 26 | ssc install streamplot, replace 27 | ``` 28 | 29 | GitHub (**v1.9**): 30 | 31 | ``` 32 | net install streamplot, from("https://raw.githubusercontent.com/asjadnaqvi/stata-streamplot/main/installation/") replace 33 | ``` 34 | 35 | 36 | The following dependencies are required: 37 | 38 | ```stata 39 | ssc install palettes, replace 40 | ssc install colrspace, replace 41 | ssc install graphfunctions, replace 42 | ``` 43 | 44 | If you want to make a clean figure, then it is advisable to load a clean scheme. These are several available and I personally use the following: 45 | 46 | ``` 47 | ssc install schemepack, replace 48 | set scheme white_tableau 49 | ``` 50 | 51 | I also prefer narrow fonts in figures with long labels. You can change this as follows: 52 | 53 | ```stata 54 | graph set window fontface "Arial Narrow" 55 | ``` 56 | 57 | 58 | ## Syntax 59 | 60 | The syntax for the latest version is as follows: 61 | 62 | ```stata 63 | streamplot y x [if] [in], by(varname) 64 | [ palette(str) smooth(num) labcond(str) offset(num) alpha(num) yreverse cat(varname) 65 | recenter(top|mid|bot) lcolor(str) lwidth(str) labsize(num) labcolor(color|palette) 66 | percent format(str) area nolabel wrap(num) tline tlcolor(str) tlwidth(str) 67 | tlpattern(str) yline(str) labprop labscale(num) wrap(num) * 68 | ] 69 | ``` 70 | 71 | See the help file `help streamplot` for details. 72 | 73 | The most basic use is as follows: 74 | 75 | ```stata 76 | streamplot y x, by(varname) 77 | ``` 78 | 79 | where `y` is the variable we want to plot, and `x` is usually the time dimension. The `by` variable splits the data into different groupings that also determines the colors. The color schemes can be modified using the `palettes(name)` option. Here any scheme from the `colorpalettes` package can be used. 80 | 81 | 82 | ## Citation guidelines 83 | Software packages take countless hours of programming, testing, and bug fixing. If you use this package, then a citation would be highly appreciated. 84 | 85 | The [SSC citation](https://ideas.repec.org/c/boc/bocode/s459060.html) is recommended. Please note that the GitHub version might be newer than the SSC version. 86 | 87 | 88 | 89 | ## Examples 90 | 91 | Set up the data: 92 | 93 | ```stata 94 | clear 95 | set scheme white_tableau 96 | graph set window fontface "Arial Narrow" 97 | 98 | use "https://github.com/asjadnaqvi/stata-streamplot/blob/main/data/streamdata.dta?raw=true", clear 99 | 100 | ``` 101 | 102 | We can generate basic graphs as follows: 103 | 104 | ```stata 105 | streamplot new_cases date, by(region) 106 | ``` 107 | 108 | 109 | 110 | ```stata 111 | streamplot new_cases date if date > 22400, by(region) smooth(6) 112 | ``` 113 | 114 | 115 | 116 | Recenter the graphs to top or bottom: 117 | 118 | ```stata 119 | streamplot new_cases date if date > 22400, by(region) smooth(6) recenter(bot) 120 | ``` 121 | 122 | 123 | 124 | ```stata 125 | streamplot new_cases date if date > 22400, by(region) smooth(6) recenter(top) 126 | ``` 127 | 128 | 129 | 130 | 131 | ```stata 132 | streamplot new_cases date if date > 22400, by(region) smooth(6) /// 133 | labcond(20000) ylabsize(1.8) lc(black) lw(0.04) 134 | ``` 135 | 136 | 137 | 138 | 139 | ```stata 140 | streamplot new_cases date if date > 22400, by(region) smooth(6) /// 141 | labcond(20000) ylabsize(1.8) lc(black) lw(0.04) format(%12.0fc) offset(20) 142 | ``` 143 | 144 | 145 | 146 | 147 | ```stata 148 | streamplot new_cases date if date > 22400, by(region) smooth(6) palette(CET D11) /// 149 | labcond(2) ylabsize(1.8) lc(black) lw(0.04) percent format(%3.2f) offset(20) ylabc(red) 150 | ``` 151 | 152 | 153 | 154 | ```stata 155 | streamplot new_cases date if date > 22400, by(region) smooth(6) palette(CET C6, reverse) /// 156 | labcond(1) ylabsize(1.8) lc(black) lw(0.04) percent format(%3.2f) offset(20) ylabc(palette) 157 | ``` 158 | 159 | 160 | 161 | 162 | Test label wrapping and condition the labels: 163 | 164 | ```stata 165 | streamplot new_cases date if date > 22400, by(region) smooth(6) palette(CET C6, reverse) wrap(25) labprop /// 166 | labcond(4e4) labsize(1.8) lc(black) lw(0.04) offset(20) labc(palette) 167 | ``` 168 | 169 | 170 | 171 | ```stata 172 | qui summ date if date > 22400 173 | 174 | local xmin = `r(min)' 175 | local xmax = `r(max)' 176 | 177 | streamplot new_cases date if date > 22400, by(region) smooth(6) palette(CET D02) /// 178 | title("My Stata stream plot") /// 179 | subtitle("Subtitle here") note("Note here") /// 180 | labcond(20000) ylabsize(1.5) lc(white) lw(0.08) /// 181 | xlabel(`xmin'(20)`xmax', angle(90)) xtitle("") 182 | ``` 183 | 184 | 185 | 186 | 187 | 188 | 189 | or a custom graph scheme: 190 | 191 | ```stata 192 | streamplot new_cases date if date > 22600, by(region) smooth(6) palette(CET CBD1) /// 193 | title("My Stata stream plot", size(6)) subtitle("with colorblind-friendly colors", size(4)) /// 194 | labcond(20000) ylabs(2) lc(black) lw(0.03) offset(25) xtitle("") /// 195 | scheme(neon) 196 | ``` 197 | 198 | where the dark background `neon` scheme is loaded from the [schemepack](https://github.com/asjadnaqvi/stata-schemepack) suite. 199 | 200 | 201 | 202 | 203 | 204 | ## v1.6 updates 205 | 206 | Test the `yreverse` option: 207 | 208 | ``` 209 | streamplot new_cases date if date > 22400, by(region) smooth(6) /// 210 | labcond(20000) ylabsize(1.8) lc(black) lw(0.04) format(%12.0fc) offset(20) yrev 211 | ``` 212 | 213 | 214 | 215 | 216 | Test the region split option. First let's define a variable: 217 | 218 | ``` 219 | gen ns = . 220 | replace ns = 2 if inlist(region, 1, 2, 5, 6, 7, 8) 221 | replace ns = 1 if inlist(region, 3, 4, 9, 10, 11, 12, 13) 222 | 223 | lab de ns 2 "North" 1 "South" 224 | lab val ns ns 225 | 226 | tab region ns 227 | ``` 228 | 229 | And plot it: 230 | 231 | ``` 232 | streamplot new_cases date if date > 22400, by(region) smooth(6) cat(ns) palette(CET D02) labcond(20000) 233 | ``` 234 | 235 | 236 | 237 | 238 | We can use the new variable itself in the `by()` option: 239 | 240 | 241 | ``` 242 | streamplot new_cases date if date > 22400, cat(ns) by(ns) smooth(6) 243 | ``` 244 | 245 | 246 | 247 | ## v1.7 updates 248 | 249 | Get the data: 250 | 251 | ``` 252 | use "https://github.com/asjadnaqvi/stata-streamplot/blob/main/data/wbgdpdata.dta?raw=true", clear 253 | 254 | drop if year < 1990 255 | gen splitvar = category!="M" 256 | ``` 257 | 258 | 259 | ``` 260 | streamplot value_real year if countrycode=="TSA", by(category) smooth(2) xsize(2) ysize(1) 261 | ``` 262 | 263 | 264 | 265 | ``` 266 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) xsize(2) ysize(1) 267 | ``` 268 | 269 | 270 | 271 | ``` 272 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Green-Orange-Teal) /// 273 | yline(0) xsize(2) ysize(1) 274 | ``` 275 | 276 | 277 | 278 | ``` 279 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Green-Orange-Teal) /// 280 | yline(0) xsize(2) ysize(1) tline 281 | ``` 282 | 283 | 284 | 285 | ``` 286 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Nuriel Stone) /// 287 | yline(0) xsize(2) ysize(1) tline tlc(white) tlw(0.8) tlp(dash) 288 | ``` 289 | 290 | 291 | 292 | ``` 293 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Green-Orange-Teal) /// 294 | yline(0) xsize(2) ysize(1) tline tlc(black) tlw(0.5) tlp(dash) 295 | ``` 296 | 297 | 298 | 299 | ``` 300 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Green-Orange-Teal) /// 301 | yline(0) xsize(2) ysize(1) tline tlc(black) tlw(0.5) tlp(dash) xtitle("") /// 302 | xlabel(1990(2)2022, angle(90)) labsize(2.2) offset(8) /// 303 | title("{fontface Arial Bold:GDP Expenditures in South Asia (Constant 2015 USD billions)}") /// 304 | note("World Bank Open Data.", size(2)) 305 | ``` 306 | 307 | 308 | 309 | 310 | ## v1.8 updates 311 | 312 | ```stata 313 | streamplot value_real year if countrycode=="TSA", by(category) cat(splitvar) smooth(2) palette(tab Green-Orange-Teal) /// 314 | yline(0) xsize(2) ysize(1) tline tlc(black) tlw(0.5) tlp(dash) xtitle("") xline(2020) /// 315 | xlabel(1990(2)2022, angle(90)) labsize(2.2) offset(8) labprop /// 316 | title("{fontface Arial Bold:GDP Expenditures in South Asia (Constant 2015 USD billions)}") /// 317 | note("World Bank Open Data.", size(2)) 318 | ``` 319 | 320 | 321 | 322 | ``` 323 | streamplot value_real year if countrycode=="TSA", by(category) smooth(2) palette(tab Green-Orange-Teal) /// 324 | xsize(2) ysize(1) xtitle("") /// 325 | xlabel(, angle(90)) labsize(2.2) offset(8) recenter(bottom) labprop /// 326 | title("{fontface Arial Bold:GDP Expenditures in South Asia (Constant 2015 USD billions)}") /// 327 | note("World Bank Open Data.", size(2)) 328 | ``` 329 | 330 | 331 | 332 | ``` 333 | streamplot value_real year if countrycode=="TSA", by(category) smooth(2) palette(tab Green-Orange-Teal) /// 334 | xsize(2) ysize(1) xtitle("") /// 335 | xlabel(, angle(90)) labsize(2.2) offset(8) recenter(bottom) labprop labcolor(palette) /// 336 | title("{fontface Arial Bold:GDP Expenditures in South Asia (Constant 2015 USD billions)}") /// 337 | note("World Bank Open Data.", size(2)) 338 | ``` 339 | 340 | 341 | 342 | 343 | ## v1.81 stacked area graph 344 | 345 | ``` 346 | streamplot value_real year if countrycode=="TSA", by(category) smooth(0) area recenter(bottom) /// 347 | xsize(2) ysize(1) xtitle("") palette(tab Green-Orange-Teal) /// 348 | xlabel(, angle(90)) labsize(2.2) offset(8) /// 349 | title("{fontface Arial Bold:GDP Expenditures in South Asia (Constant 2015 USD billions)}") /// 350 | note("World Bank Open Data.", size(2)) 351 | ``` 352 | 353 | 354 | 355 | 356 | ## Feedback 357 | 358 | Please open an [issue](https://github.com/asjadnaqvi/stata-streamplot/issues) to report errors, feature enhancements, and/or other requests. 359 | 360 | 361 | ## Change log 362 | 363 | **v1.9 (08 Feb 2025)** 364 | - `droplow` has been taken out. All categories are now plotted even if they have one observation. If categories end in the middle, they are not labeled. 365 | - The option `wrap` now requires the [graphfunctions](https://github.com/asjadnaqvi/stata-graphfunctions) package. Word boundaries are now respected. 366 | - `laboffset()` added to displace labels. Negative values would make the labels closer to the stream. 367 | - Fixed several bugs. 368 | 369 | **v1.82 (10 Jun 2024)** 370 | - Added `wrap()` option for label wrapping. 371 | - Minor code fixes. 372 | 373 | **v1.81 (30 Apr 2024)** 374 | - Added `area` option to allow stacked area graphs. 375 | 376 | **v1.8 (25 Apr 2024)** 377 | - Added `labprop` and `labscale()` options to allow easy label scaling. 378 | - Added `share` and `percent` as substitutes. 379 | - Major code rework to optimize the speed of the graph generation. 380 | - Generic twoway options added. 381 | - 382 | 383 | **v1.7 (01 Apr 2024)** 384 | - Added trendline options: `tline`, `tlcolor()`, `tlpattern()`, `tlwidth()`. 385 | - Added additional checks for plotting data. 386 | - Better handling of missing values and categories. 387 | 388 | **v1.61 (15 Jan 2024)** 389 | - Fixed issues with locals. 390 | - Change `ylabcolor()` and `ylabsize()` to `labcolor()` and `labsize()` respectively. 391 | 392 | **v1.6 (15 Oct 2023)** 393 | - Major update with the `cat()` option added to compare top versus bottom streams. 394 | - Option `yreverse` fixed. 395 | - Option `nolab` fixed. 396 | - Several internal routines rewritten and cleaned up. 397 | - The option `percent()` is now defined in the 0-100 (or higher range). Changed from the 0-1 range. 398 | 399 | **v1.52 (25 Aug 2023)** 400 | - Support for `aspect()`, `saving()`, `xscale()`, and `graphregion()` added. 401 | 402 | **v1.51 (28 May 2023)** 403 | - Cleaned up `labcond()` to align it with other packages. 404 | - `offset()` changed to percentages to align it with other packages. 405 | - Minor code cleanups, updates to defaults, and help file. 406 | 407 | **v1.5 (20 Nov 2022)** 408 | - Option to recenter the graphs added. 409 | - Improve the precision of the calculations. 410 | 411 | **v1.4 (08 Nov 2022)** 412 | - Major code cleanup. 413 | - The command now does error checks on the number of observations. 414 | - The command now correct deals with sequence of variables. 415 | - Additional `colorpalette` options added. 416 | - Several fixes to the help file. 417 | 418 | **v1.3 (20 Jun 2022)** 419 | - ado distribution date added. 420 | - ylabel color, format, and percentages added (Thanks to Marc Kaulisch who suggested and contributed to these options). 421 | - Fixes to variables precisions. 422 | - y-label color fixed. Labels can either take on a named color, or they can be assigned the same colors as the color palette. 423 | 424 | **v1.2 (06 Jun 2022)** 425 | - Fixes to value labels no passing through to graphs (Thanks to Marc Kaulisch). 426 | - Several graph options modified to passthru for better integration with twoway options. 427 | - Smoothing parameter adjusted 428 | - Error checks added. If there are too few observations per group, the command will abort. 429 | 430 | **v1.1 (08 Apr 2022)** 431 | - Public release. Several options and features added. 432 | 433 | **v1.0 (06 Aug 2021)** 434 | - Beta version 435 | --------------------------------------------------------------------------------