Code to make a dot and 95% confidence interval figure in Stata

Dot and confidence interval figures in Stata

Stata has a pretty handy -twoway dot- code that can be combined with -twoway rcap- to make the code below. The only annoying thing is that -twoway dot- inserts a line that connects your dot with the Y-axis. The code below will make this sharp-looking figure without the connecting line.

Also, there is a bonus code at the end to make this figure:

 

First step, make an Excel file

I made an excel file with the below columns called “dot and 95 percent ci data.xlsx” saved in the same folder as my .do file. This figure will display row 1 at the top and row 14 at the bottom. The gaps in between the lines are the absent rows 3,6, 9, and 12. Group tells Stata if you want a hollow or solid dot. Proportion is the point estimate and low95 and high95 are the surrounding 95% confidence intervals.

Note that the data here are made up and are not related to any actual ongoing clinical investigation. 

Next step, make a .do file

In the same folder as the Excel file, copy/paste/save the code below as a .do file. Close Excel and close Stata then find the .do file from Windows Explorer and double click it. Doing this will force Stata to set the working directory as the folder containing the .do file (and the Excel file).

If the code won’t work, you probably have Excel open. Close it and try again.

That’s it!

Share and enjoy. Code below.

********************************************************************************
******************************IMPORT DATA HERE**********************************
********************************************************************************
import excel "dot and 95 percent ci data.xlsx", firstrow clear
destring, replace

******************************************************************************** 
******************************CODE STARTS HERE********************************** 
******************************************************************************** 
capture ssc install scheme-burd, replace // this installs more color patterns. 
set scheme burd4 // I like burd4.

twoway ///
(dot proportion row if group ==1, horizontal dcolor(bg)) /// dcolor(bg) hides dotted line 
/// connecting the dot with the Y axis by matching it with the background. 
(dot proportion row if group ==2, horizontal dcolor(bg)) ///
(rcap low95 high95 row, horizontal), /// code for 95% CI
legend(row(1) order(1 "legend 1" 2 "legend 2") pos(6)) /// legend at 6 o'clock position
ylabel(1.5 "Model A" 4.5 "Model B" 7.5 "Model C" 10.5 "Model D" 13.5 "Model E", angle(0) noticks) ///
/// note that the labels are 1.5, 4.5, etc so they are between rows 1&2, 4&5, etc.
/// also note that there is a space in between different rows by leaving out rows 3, 6, 9, and 12 
xlabel(.95 " " 1 "1.0" 1.1 "1.1" 1.2 "1.2" 1.3 "1.3" 1.4 "1.4" 1.5 "1.5" 1.6 " ", angle(0)) /// no 1.6 label
xtitle("X axis") /// 
ytitle("Y axis") /// 
yscale(reverse) /// y axis is flipped
/// aspect (next line) is how tall or wide the figure is
aspect(.5)

graph export "dot and 95 percent ci figure.png", replace width(2000)
//graph export "dot and 95 percent ci figure.tif", replace width(2000)

Bonus code for an AJC paper figure

This figure is from a 2018 manuscript that we published in AJC using SPRINT data.

Here’s a view of our “024a arr.xlsx” Excel file that contained the data that went into this figure. The label1 and label2 were to help me make sense of everything while writing this code and aren’t actually used. All that is called by the code below is row, group, proportion, low95, and high95.

Here is the code:

********************************************************************************
******************************IMPORT DATA HERE**********************************
********************************************************************************
import excel "024a arr.xlsx", firstrow clear
destring, replace

******************************************************************************** 
******************************CODE STARTS HERE********************************** 
******************************************************************************** 
set scheme s1color

twoway ///
(dot proportion row, horizontal ndot(0) mcolor(black)) /// ndots(0) hides dotted line 
/// connecting the dot with the Y axis 
(rcap low95 high95 row, horizontal lcolor(black)), /// code for 95% CI
legend(row(2) order(1 "Point Estimate" 2 "95% CI") pos(6)) /// legend at 6 o'clock position
ylabel(1 "All" 3 "Q1" 4 "Q2" 5 "Q3" 6 "Q4" 8 "<10%" 9 "≥10%" 12 "All" 14 "Q1" 15 "Q2" 16 "Q3" 17 "Q4" 19 "<10%" 20 "≥10%", angle(0) noticks) ///
/// there is a space in between different rows by leaving out rows 3, 6, 9, and 12 
xlabel(-5 "-5%" 0 "0%" 5 "5%" 10 "10%", angle(0)) ///
xtitle("Risk difference") /// 
ytitle(" SAEs ASCVD Events") /// the leading space just makes the label sit centered in the figure
xline(0, lcolor(gs4)) ///
yscale(reverse) /// 
text(4.5 11 "P=0.84", place(e) size(small)) ///
text(8.5 11 "P=0.67", place(e) size(small)) ///
text(15.5 11 "P=0.82", place(e) size(small)) ///
text(19.5 11 "P=0.95", place(e) size(small)) ///
aspect(1.68)


graph export "024a arr figure.png", replace width(2000) 
graph export "024a arr figure.tif", replace width(2000) // tif file sent in for publication