Skip to content

asjadnaqvi/stata-bimap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StataMin issues license Stars version release

Installation | Syntax | Citation guidelines | Examples | Feedback | Change log


bimap_banner_v2

bimap v2.1

(22 Aug 2024)

This package provides the ability to draw bi-variate maps in Stata. It is based on the Bi-variate maps Guide.

As of version 2.0 (released on 22nd August 2024), bimap uses geoplot for Stata versions 17 or newer, and spmap for Stata versions 16 or earlier. Users with newer versions can still opt to use the original spmap implementation by defining the original code (with minor changes, see below) and using the option old. Information on which version is detected and which map package is used can be displayed by using the detail option.

As more and more users switch to newer Stata versions, the spmap implementation will eventually be phased out. As of v2.0 it will no longer be developed further.

Installation

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 (v2.1):

ssc install bimap, replace

Or it can be installed from GitHub (v2.1):

net install bimap, from("https://raw.githubusercontent.com/asjadnaqvi/stata-bimap/main/installation/") replace

For using the command with geoplot the following packages are required:

ssc install geoplot, replace
ssc install moremata, replace
ssc install palettes, replace
ssc install colrspace, replace
ssc install graphfunctions, replace

For using the command with spmap the following packages are required:

ssc install spmap, replace
ssc install palettes, replace
ssc install colrspace, replace
ssc install graphfunctions, replace

Even if you have these packages installed, please check for updates: ado update, update.

Optional: Users can also install the geo2xy package for projection transformations, even though geoplot supports projects internally as well:

ssc install geo2xy, replace

Optional: 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.

I also prefer narrow fonts in figures with long labels. You can change this as follows:

graph set window fontface "Arial Narrow"

Syntax for Stata versions 17 or newer

The syntax for the latest version is as follows:

bimap vary varx [if] [in], frame(name) 
        [ geo(options) geopost(options)  
          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) detail
          textsize(str) textlabsize(str) vallabsize(str) textcolor(str) textlabcolor(str) vallabcolor(str) 
          xscale(num) yscale(num) * ]

with the following minimal syntax requirement:

bimap vary varx, frame(framename)

Syntax for Stata versions 16 or older

bimap vary varx [if] [in], shp(shapefile) 
        [ old polygon(str) line(str) point(str) label(str) arrow(str) diagram(str) scalebar(str) 
          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) detail
          textsize(str) textlabsize(str) vallabsize(str) textcolor(str) textlabcolor(str) vallabcolor(str) 
          xscale(num) yscale(num) * ]

with the following minimal syntax requirement:

bimap vary varx, shp(shapefile)

Note that v2.0 changes the use of the shapefile syntax. This might be a minor inconvinience for older users of bimap.

See help bimap for details.

Citation guidelines

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 = {2.0},
   date = {2024-08-22}
}

or simple text

Naqvi, A. (2024). Stata package "bimap" version 2.0. Release date 22 August 2024. https://github.com/asjadnaqvi/stata-bimap.

or see SSC citation (updated once a new version is submitted)

Examples

The examples showcase both the syntax for the use with geoplot (first syntax) and spmap (second syntax). The map outputs have been aligned to the extent possible but very minor differences in outputs might remain. Additionally, as geoplot is still in active development, output might break with latest updates or syntax might change. Please report these as soon as possible.

Since I am using Stata 18+, I have to specify old option to pass the syntax to use spmap. This might be uncessary if you have older Stata versions.

Users can either download the files from GIS and dump them in a folder or directly get them from Stata:

Set up the data:

cd <change path to the working directory>

foreach x in county county_shp2 state state_shp2 usa_county2 {
	copy "https://github.com/asjadnaqvi/stata-bimap/raw/main/GIS/`x'.dta" "`x'.dta", replace
}

Test whether the geoplot is working properly. First set up the layer frames:

// create the geoframes
geoframe create county, replace shp(county_shp2)
geoframe create state, replace shp(state_shp2)
geoframe create cities usa_county2, replace shp(county_shp2)  // minor example of pairing with point location data. 

// make the country frame active
frames change county 


destring _all, replace
merge 1:1 STATEFP COUNTYFP using county_race
keep if _m==3
drop _m	
geoplot (area county share_afam) (line state)

Test whether the spmap is working properly:

spmap share_afam using county_shp2, id(_ID) clm(custom) clb(0(10)100) fcolor(Heat)

Basic bimap

Let's test the bimap command:

bimap share_hisp share_afam, frame(county) cut(pctile) palette(pinkgreen) 
bimap share_hisp share_afam, shp(county_shp2) old cut(pctile) palette(pinkgreen)

bimap share_hisp share_afam , frame(county) cut(pctile) palette(pinkgreen) count values
bimap share_hisp share_afam, shp(county_shp2) old cut(pctile) palette(pinkgreen) count values

bimap share_hisp share_afam , cut(pctile) palette(pinkgreen) percent values frame(county).
bimap share_hisp share_afam, shp(county_shp2) old cut(pctile) palette(pinkgreen) percent values

bimap share_hisp share_afam, frame(county) cut(equal) palette(pinkgreen) count values
bimap share_hisp share_afam, shp(county_shp2) old cut(equal) palette(pinkgreen) count values

Legacy palettes

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, frame(county) cut(pctile) palette(`x') percent title("Legacy scheme: `x'") 

			local ++i
}
local i = 1

foreach x in pinkgreen0 bluered0 greenblue0 purpleyellow0 yellowblue0 orangeblue0 brew1 brew2 brew3 census rgb viridis gscale {

		bimap share_hisp share_afam, shp(county_shp2) old cut(pctile) palette(`x') percent title("Legacy scheme: `x'") 

		local ++i
}

Advanced examples

bimap share_asian share_afam, cut(pctile) palette(bluered) frame(county)  ///
	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 ///
		 osize(none) geo((line state)) 
bimap share_asian share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) frame(county)  ///
	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 ///
		 osize(none) geo((line state, lc(white) lw(0.2)))  
bimap share_asian share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) frame(county)  ///
	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 ///
		 osize(none)  geo((line state, lc(black) lw(0.2)))  
bimap share_asian share_hisp, shp(county_shp2) old 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)) 

Passing advanced options


bimap share_hisp share_afam, cut(pctile) palette(pinkgreen) percent  frame(county)  ///
	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  ///
		 osize(none) ///
		 geo( (line state, lc(black) lw(0.2))  (point cities [w = tot_pop] if tot_pop>1e5, mc(lime%80) msize(0.8) lc(black))  )  
bimap share_hisp share_afam, shp(county_shp2) old 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) )  

v1.4 updates

Let's make a bimap with percentiles as cut-offs and percentages shown in boxes:

bimap share_hisp share_afam, cut(pctile) palette(orangeblue) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent  ///
			osize(none)  geo((line state, lc(black) lw(0.2)))  
bimap share_hisp share_afam, shp(county_shp2) old 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)) 

Custom cut-offs (v1.8)

we can now modify the cut-offs as follows:

bimap share_hisp share_afam, cut(pctile) palette(orangeblue) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent  ///
			osize(none)  geo((line state, lc(black) lw(0.2)))  
bimap share_hisp share_afam, shp(county_shp2) old 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, cuty(0(25)100) cutx(0(25)100)  formatx(%3.0f) formaty(%3.0f)  palette(orangeblue) frame(county)    ///
		 note("Data from the US Census Bureau.") ///	
		 texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
			osize(none) geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cutx(0 2 6 100) formatx(%5.0f)   palette(orangeblue) frame(county)    ///
		 note("Data from the US Census Bureau.") ///	
		 texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values percent  ///
		osize(none) geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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)) 

legend checks + offset (v1.8)

bimap share_hisp share_afam, cut(pctile) palette(census) frame(county)  ///
		 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)  ///
		 geo((line state, lc(black) lw(0.2))) showlegend ///
		 geopost( ///
			compass ///
			sbar(length(1000) units(km) position(sw)) ///
			)	
bimap share_hisp share_afam, shp(county_shp2) old 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, shp(county_shp2) old 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) 

new legend checks (v1.9)

Check for legend color options:

bimap share_asian share_afam, cut(pctile) frame(county)   ///
	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) ///
		 osize(none) ///
		 geo((line state, lc(white) lw(0.3)))
bimap share_asian share_afam, shp(county_shp2) old 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) ///
		 osize(none) ///
		 polygon(data("state_shp2") ocolor(white) osize(0.3))

Check for label wrapping in the legend:

bimap share_asian share_afam, cut(pctile) frame(county)    ///
	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  ///
		 osize(none) ///
		 geo((line state, lc(white) lw(0.3)))
bimap share_asian share_afam, shp(county_shp2) old 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  ///
		 osize(none) ///
		 polygon(data("state_shp2") ocolor(white) osize(0.3))

Check for hiding the legend:

bimap share_asian share_afam, cut(pctile) frame(county)  ///
	title("{fontface Arial Bold:A Stata bivariate map}") note("Data from the US Census Bureau.") ///	
		 osize(none) ///
		 geo((line state, lc(white) lw(0.3))) nolegend
bimap share_asian share_afam, shp(county_shp2) old 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

v1.5 updates

If condition checks with legends

bimap share_hisp share_afam if STATEFP==36, cut(pctile) palette(census) frame(county)   ///
		 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)  ///
		 		 geo((line state if _ID==19, lc(black) lw(0.2))) nolegend
bimap share_hisp share_afam if STATEFP==36, shp(county_shp2) old 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)

v1.6 updates

bimap share_hisp share_afam, cut(pctile) palette(orangeblue) bins(5) frame(county) ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) binx(4) biny(5) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) binx(3) biny(8) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) bins(8) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values   ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) bins(8) frame(county)  ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values   ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) clr0(white) clrx(red) bins(6) clrsat(10) frame(county)   ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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, cut(pctile) palette(orangeblue) bins(4)  percent frame(county)   ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values   ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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)) 

showing proper bins (v1.6)

Bins can be scaled to show actual division. Use this cautiously especially if the data distribution is highly skewed.

bimap share_hisp share_afam, cuty(0 20 60 100) cutx(0 30 50 75 100) palette(orangeblue) formatx(%5.0f)  formaty(%5.0f) binsproper frame(county)   ///
		note("Data from the US Census Bureau.") ///	
		texty("Share of Hispanics") textx("Share of African Americans") texts(3.5) textlabs(3) values count  ///
		 osize(none) ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old 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)) 

discrete variables (v1.7)

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, palette(yellowblue) values count ydisc frame(county) 
bimap discy share_afam, shp(county_shp2) old palette(yellowblue) values count ydisc

bimap share_hisp discx, palette(yellowblue) values count xdisc frame(county) 
bimap share_hisp discx, shp(county_shp2) old palette(yellowblue) values count xdisc

bimap discy discx, palette(yellowblue) values count xdisc ydisc frame(county) 
bimap discy discx, shp(county_shp2) old palette(yellowblue) values count xdisc ydisc

missing data (v1.81)

replace share_hisp = . if stname=="Texas"
bimap share_hisp share_afam, palette(orangeblue)  frame(county)  ///
		 ndfcolor(pink) ndocolor(lime) ndsize(0.2)  ///
		 values count  ///
		 geo((line state, lc(black) lw(0.2)))
bimap share_hisp share_afam, shp(county_shp2) old palette(orangeblue)    ///
		 ndfcolor(pink) ndocolor(lime) ndsize(0.3)  ///
		 values count  ///
		 polygon(data("state_shp2") ocolor(black) osize(0.2)) 

Feedback

Please open an issue to report errors, feature enhancements, and/or other requests.

Change log

v2.1 (18 October 2024)

  • Supporting for better label wrapping added using graphfunctions. The latest version of this package is required.
  • Minor syntax cleanups.

v2.0 (22 August 2024)

  • Major update. Support for geoplot for Stata versions 17 or newer. Support for spmap for Stata versions 16 or older. Versions are auto detected.
  • Stata 17 or newer users can use the option old to call in the spmap version. This ensures that the code of seasoned bimap users does not break.
  • Minor change in syntax for spmap versions from bimap y x using shapefile to bimap y x, shp(shapefile). This is to ensure consistency for upcoming releases.
  • Option detail added to show which Stata version is detected and which map program is used. This might be useful in case you want to have more information.

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() and cuty() 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() and labygap() 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 and ydiscrete 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 for arrow, diagram, and scalebar.

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.