├── .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 |      
4 |
5 |
6 | [Installation](#Installation) | [Syntax](#Syntax) | [Citation guidelines](#Citation-guidelines) | [Examples](#Examples) | [Feedback](#Feedback) | [Change log](#Change-log)
7 |
8 | ---
9 |
10 |
11 | 
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 |
--------------------------------------------------------------------------------