Installation | Syntax | Citation guidelines | Examples | Feedback | Change log
(19 Jun 2024)
This package provides the ability to draw bi-variate maps in Stata. It is based on the Bi-variate maps Guide.
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. All examples are updated to the latest version and might not be compatible with the old ones. Please check the documentation and change logs.
The package can be installed from SSC (v1.82):
ssc install bimap, replace
Or it can be installed from GitHub (v1.9):
net install bimap, from("https://raw.githubusercontent.com/asjadnaqvi/stata-bimap/main/installation/") replace
The spmap
and palettes
package is required to run this command:
ssc install spmap, replace
ssc install palettes, replace
ssc install colrspace, replace
Even if you have these packages installed, please check for updates: ado update, update
.
If you want to make a clean figure, then it is advisable to load a clean scheme. I personally use the following:
ssc install schemepack, replace
set scheme white_tableau
You can also push the scheme directly into the graph using the scheme(schemename)
option. See the help file for details or the example below.
I also prefer narrow fonts in figures with long labels. You can change this as follows:
graph set window fontface "Arial Narrow"
This command is a wrapper for spmap
and assumes that you have shapefiles in Stata and are comfortable with making maps.
The syntax for the latest version is as follows:
bimap vary varx [if] [in], [ palette(name) reverse clr0(str) clrx(str) clry(str) clrsaturate(num)
cut(pctile|equal) cutx(numlist) cuty(numlist) binsproper bins(num >=2) binx(num >=2) biny(num >=2) values count
percent showlegend ocolor(str) osize(str) ndocolor(str) ndfcolor(str) ndfsize(str) xdiscrete ydiscrete
labxgap(num) labygap(num) textx(str) texty(str) formatx(str) formaty(str)
textsize(str) textlabsize(str) vallabsize(str) textcolor(str) textlabcolor(str) vallabcolor(str)
xscale(num) yscale(num) polygon(options) line(options) point(options) label(options) arrow(options)
diagram(options) scalebar(options) * ]
See the help file help bimap
for details.
The most basic use is as follows:
bimap vary varx using *shapefile*
See helpfile for further details
Software packages take countless hours of programming, testing, and bug fixing. If you use this package, then a citation would be highly appreciated. Suggested citations:
in BibTeX
@software{bimap,
author = {Naqvi, Asjad},
title = {Stata package ``bimap''},
url = {https://github.com/asjadnaqvi/stata-bimap},
version = {1.9},
date = {2024-06-19}
}
or simple text
Naqvi, A. (2024). Stata package "bimap" version 1.9. Release date 19 June 2024. https://github.com/asjadnaqvi/stata-bimap.
or see SSC citation (updated once a new version is submitted)
Download the files from GIS and dump them in a folder.
Set up the data:
clear
set scheme white_tableau
graph set window fontface "Arial Narrow"
// set the directory to the GIS folder
// cd <path>
use county, clear
destring _all, replace
merge 1:1 STATEFP COUNTYFP using county_race
keep if _m==3
drop _m
save usa_county2.dta, replace
Test whether the spmap
is working properly:
spmap share_afam using county_shp2, id(_ID) clm(custom) clb(0(10)100) fcolor(Heat)
spmap share_hisp using county_shp2, id(_ID) clm(custom) clb(0(10)100) fcolor(Heat)
Let's test the bimap
command:
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(pinkgreen)
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(pinkgreen) count values
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(pinkgreen) percent values
bimap share_hisp share_afam using county_shp2, cut(equal) palette(pinkgreen) count values
These old palettes can still be used and will default to 3x3 bins.
local i = 1
foreach x in pinkgreen0 bluered0 greenblue0 purpleyellow0 yellowblue0 orangeblue0 brew1 brew2 brew3 census rgb viridis gscale {
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(`x') percent title("Legacy scheme: `x'")
graph export bimap3_`i'.png, replace wid(2000)
local i = `i' + 1
}
bimap share_asian share_afam using county_shp2, cut(pctile) palette(bluered) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
textx("Share of African Americans") texty("Share of Asians") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(white) osize(0.3))
bimap share_asian share_afam using county_shp2, cut(pctile) palette(yellowblue) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
textx("Share of African Americans") texty("Share of Asians") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_asian share_hisp using county_shp2, cut(pctile) palette(orangeblue) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
textx("Share of Hispanics") texty("Share of Asians") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
Since bimap
is a wrapper of spmap
, we can pass information for other layers as well including dots. Below we use the file we saved in the first step to plot the population of counties:
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(pinkgreen) percent ///
title("{fontface Arial Bold:A Stata bivariate map}") ///
note("Data from the US Census Bureau. Counties with population > 100k plotted as proportional dots.", size(1.8)) ///
textx("Share of African Americans") texty("Share of Hispanics") texts(3.5) textlabs(3) values ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(white) osize(0.3)) ///
point(data("usa_county2") x(_CX) y(_CY) select(keep if tot_pop>100000) proportional(tot_pop) psize(absolute) fcolor(lime%85) ocolor(black) osize(0.12) size(0.9) )
Let's make a bimap
with percentiles as cut-offs and percentages shown in boxes:
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
we can now modify the cut-offs as follows:
bimap share_hisp share_afam using county_shp2, cuty(0(20)100) cutx(0(20)100) palette(orangeblue) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
Cut-offs can be formatted as follows:
bimap share_hisp share_afam using county_shp2, cuty(0(25)100) cutx(0(25)100) formatx(%3.0f) formaty(%3.0f) palette(orangeblue) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
If we define only one custom cut-off, the other will automatically take on the pctile values:
bimap share_hisp share_afam using county_shp2, cutx(0 2 6 100) formatx(%5.0f) palette(orangeblue) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
spmap
legend options can be passed to bimap
to describe additional layers:
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(census) ///
note("Data from the US Census Bureau.", size(small)) ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.2) textlabs(3) values percent ///
ocolor(black) osize(0.03) ///
polygon(data("state_shp2") ocolor(black) osize(0.2) legenda(on) leglabel(State boundaries)) ///
scalebar(units(500) scale(1/1000) xpos(100) label(Kilometers)) ///
showleg legenda(off) legend(pos(7) size(5)) legstyle(2)
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(census) ///
note("Data from the US Census Bureau.", size(small)) ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.2) textlabs(3) values percent labxgap(0.05) labygap(0.05) ///
ocolor(black) osize(0.03) ///
polygon(data("state_shp2") ocolor(black) osize(0.2) legenda(on) leglabel(State boundaries)) ///
scalebar(units(500) scale(1/1000) xpos(100) label(Kilometers)) ///
showleg legenda(off) legend(pos(7) size(5)) legstyle(2)
Check for legend color options:
bimap share_asian share_afam using county_shp2, cut(pctile) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
textx("Share of African Americans") texty("Share of Asians") values count textcolor(lime) textlabcolor(blue) vallabc(red) ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(white) osize(0.3))
Check for label wrapping in the legend:
bimap share_asian share_afam using county_shp2, cut(pctile) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
textx("Share of African Americans") texty("Share of Asians") wrap(16) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(white) osize(0.3))
Check for hiding the legend:
bimap share_asian share_afam using county_shp2, cut(pctile) ///
title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(white) osize(0.3)) nolegend
If condition checks with legends
bimap share_hisp share_afam using county_shp2 if STATEFP==36, cut(pctile) palette(census) ///
title("New York") ///
note("Data from the US Census Bureau.", size(small)) ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.2) textlabs(3) values percent ///
ocolor(black) osize(0.03) ///
polygon(data("state_shp2") select(keep if _ID==19) ocolor(black) osize(0.2) legenda(on) leglabel(State boundaries)) ///
showleg legenda(off) legend(pos(7) size(5)) legstyle(2)
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) bins(5) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) binx(4) biny(5) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) binx(3) biny(8) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) bins(8) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.1))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) reverse bins(8) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) clr0(white) clrx(red) bins(6) clrsat(10) ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
bimap share_hisp share_afam using county_shp2, cut(pctile) palette(orangeblue) bins(4) percent ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
Bins can be scaled to show actual division. Use this cautiously especially if the data distribution is highly skewed.
bimap share_hisp share_afam using county_shp2, cuty(0 20 60 100) cutx(0 30 50 75 100) palette(orangeblue) formatx(%5.0f) formaty(%5.0f) binsproper ///
note("Data from the US Census Bureau.") ///
texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count ///
ocolor() osize(none) ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
Let's make some variables discrete:
xtile discx = share_afam, n(4)
gen discy = share_hisp < 10
lab de dx 1 "Catx 1" 2 "Catx 2" 3 "Catx 3" 4 "Catx 4"
lab val discx dx
lab de dy 0 "Caty 0" 1 "Caty 1"
lab val discy dy
tab discy discx, m
We can also now declare these variables as discrete while using bimap
in any combination:
bimap discy share_afam using county_shp2, palette(yellowblue) values count ydisc
bimap share_hisp discx using county_shp2, palette(yellowblue) values count xdisc
bimap discy discx using county_shp2, palette(yellowblue) values count xdisc ydisc
use county, clear
destring _all, replace
merge 1:1 STATEFP COUNTYFP using county_race
keep if _m==3
drop _m
replace share_hisp = . if stname=="Texas"
bimap share_hisp share_afam using county_shp2, palette(orangeblue) ///
ndfcolor(pink) ndocolor(lime) ndsize(0.3) ///
values count ///
polygon(data("state_shp2") ocolor(black) osize(0.2))
Please open an issue to report errors, feature enhancements, and/or other requests.
v1.9 (19 June 2024)
- Fixed and added several options to control legends:
textcolor()
,textlabcolor()
,vallabcolor()
. - Better options for
textsize()
,textlabsize()
,vallabsize()
. - Added
wrap()
to wrap labels in legends. - Added
nolegend
option to generate maps without a bi-variate legend. This is useful is several maps are being generated with a controlled legend and need to be combined in one figure. - Several improvements to graph passthru options.
v1.82 (04 May 2024)
- Added
textcolor()
to control random colors appearing in legend labels under some schemes. - Backend improvements to some defaults.
v1.81 (22 Aug 2023)
- Fixed a bug where missing data points where getting dropped (reported by Steve Johnson).
- Fixed passthru of the
ndisze()
option.
v1.8 (26 Jun 2023)
- Changed the ways
cutx()
andcuty()
are calculated (requested by Paul Hufe). These now take on lists which are used as provided. - Removed
textgap()
that was left over from the old legend code. - Added
labxgap()
andlabygap()
to allows users to offset the labels and improved the position of the legend axes titles. - Various improvements including
v1.7 (15 Jun 2023)
- Added two new options
xdiscrete
andydiscrete
to support discrete variables.
v1.62 (19 May 2023)
- Fixed bugs in legend labels (reported by Kit Baum). Minor improvements.
v1.61 (12 Apr 2023)
- Fixed a major bug in the legend. The boxes were not rescaling properly.
v1.6 (17 Mar 2023) (major update)
- Scalable color palettes.
- Customizable bins.
- Customizable colors.
- Dynamic scalable legends.
- Option for proper spacing of bins on legends.
- Several defaults and checks added.
- Several quality of life adjustments to make
bimap
easier to use.
v1.51 (14 Nov 2022)
- Minor fixes to legend text options.
v1.5 (05 Nov 2022)
- Three new palettes added:
rgb
,viridis
,gscale
. - Added
spmap
passthru options forarrow
,diagram
, andscalebar
.
v1.4 (04 Oct 2022)
- Added the option to add custom cut-offs.
- Added the option to format cut-offs,
- Added the option to show default
spmap
legends. - Code clean up. New error checks.
v1.33 (29 Sep 2022)
- Bug fixes to
spmap
passthru options. - Add a new option
textgap
to allow adjustment of the distance of axes labels to the legend.
v1.32 (19 Aug 2022)
- Fixed an error in variable name comparisons (thanks to Cristian Jordan Diaz).
v1.31 (20 Jun 2022)
- Error fix in cut-offs skipping the last shape file (thanks to Mattias Öhman).
- Fixed color assignments to the 3x3 groups. If a group was missing, the colors were wrongly assigned.
v1.3 (26 May 2022)
- Percent option added to legend to show box share (thanks to Kit Baum).
- Legend corner label made lighter for visibility.
- Four special use palettes added:
brew1
,brew2
,brew3
,brew4
,census
.
v1.2 (29 Apr 2022)
- Fixed a bug in cut-off groupings (thanks to Ruth Watkinson).
- Error in how cut-off values are collected is fixed.
- Two palettes added
yellowblue
,orangeblue
. If you have more palette suggestions, then please let me know! - Several
spmap
additional layer commands added as passthru options (thanks to Pierre-Henri Bono). - Count of each category added as an option.
- Several bug fixes and error checks added.
v1.1 (14 Apr 2022)
- Errors in ado file corrected.
- Help file was missing a couple of options.
v1.0 (08 Apr 2022)
- Public release.