{"id":246,"date":"2018-07-11T14:38:25","date_gmt":"2018-07-11T18:38:25","guid":{"rendered":"http:\/\/blog.uvm.edu\/tbplante\/?p=246"},"modified":"2022-10-11T11:38:47","modified_gmt":"2022-10-11T15:38:47","slug":"making-scatterplots-and-bland-altman-plots-in-stata","status":"publish","type":"post","link":"https:\/\/blog.uvm.edu\/tbplante\/2018\/07\/11\/making-scatterplots-and-bland-altman-plots-in-stata\/","title":{"rendered":"Making Scatterplots and Bland-Altman plots in Stata"},"content":{"rendered":"\n<p><strong><em>NOTE: I have more recently put together user-friendly code on <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.uvm.edu\/tbplante\/2022\/10\/10\/making-a-scatterplot-with-r-squared-and-percent-coefficient-of-variation-in-stata\/\" target=\"_blank\">scatterplots <\/a>and <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.uvm.edu\/tbplante\/2022\/10\/11\/making-a-bland-altman-plot-with-printed-mean-and-sd-in-stata\/\" target=\"_blank\">Bland-Altman plots<\/a>. Go check those pages out.<\/em><\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scatterplots with a fitted line<\/h2>\n\n\n\n<p>This is pretty straightforward in Stata. This is a variation of a figure that I made for a <a href=\"https:\/\/www.ncbi.nlm.nih.gov\/pmc\/articles\/PMC4922794\/\">JAMA Internal Medicine paper<\/a>. (I like to think that the original figure was publication quality, but they had their graphics team redo it in their own format.) This contains a diagonal line of unity and cutoffs for systolic hypertension as vertical\/horizontal bars. Different from the publication version, this includes a thick dotted fitted line.<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile\" style=\"grid-template-columns:85% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"568\" height=\"303\" src=\"http:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture.png\" alt=\"\" class=\"wp-image-247 size-full\" srcset=\"https:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture.png 568w, https:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture-300x160.png 300w\" sizes=\"auto, (max-width: 568px) 100vw, 568px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"has-large-font-size\"><\/p>\n<\/div><\/div>\n\n\n\n<p>This code actually makes two different scatterplots then merges them together and puts labels over the merged version.<\/p>\n\n\n\n<p>The scatter function here wants a Y-axis variable and X-axis variable. The two variables were <em>ibp_sbp_pair<\/em>&nbsp;(Y-axis) and <em>average_sbp_omron_23<\/em>&nbsp;(X-axis) for systolic and&nbsp;<em>ibp_dbp_pair<\/em> and <em>average_dbp_omron_23<\/em> for diastolic.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Bland-Altman plots<\/h2>\n\n\n\n<p>This is from the same paper.<\/p>\n\n\n\n<div class=\"wp-block-media-text alignwide is-stacked-on-mobile\" style=\"grid-template-columns:85% auto\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"570\" height=\"309\" src=\"http:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture-1.png\" alt=\"\" class=\"wp-image-250 size-full\" srcset=\"https:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture-1.png 570w, https:\/\/blog.uvm.edu\/tbplante\/files\/2018\/07\/Capture-1-300x163.png 300w\" sizes=\"auto, (max-width: 570px) 100vw, 570px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"has-large-font-size\"><\/p>\n<\/div><\/div>\n\n\n\n<p>Again, two different B-A plots that are merged then labels applied. The dotted line is relative mean difference, the long dashed lines are +\/- 2 SD.<\/p>\n\n\n\n<p>As far as Stata&#8217;s graph maker is concerned, this is a scatterplot. You just need to set up all of the variables intentionally to trick it into rendering a B-A plot. The Y-axis is the difference between the variables and the X-axis is a mean of the variables.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Code for both figures follows.<\/h2>\n\n\n<pre>**********scatterplot ave with lines of fit\n***sbp\ntwoway (lfit ibp_sbp_pair average_sbp_omron_23, lcolor(gray) lpattern(dash) lwidth(vthick)) \/\/\/ line of fit code\n(function y=x, ra(average_sbp_omron_23) clcolor(gs4)) \/\/\/ diagonal line of unity\n(scatter ibp_sbp_pair average_sbp_omron_23 , mcolor(black) msize(vsmall)), \/\/\/ make dots appear for scatter, y x axis\nlegend(off) \/\/\/ hide legend\ntitle(\"Systolic BP\", color(black)) \/\/\/\nytitle(\"\") \/\/\/ no title, will add when merging SBP and DBP\nxtitle(\"\") \/\/\/ ditto\nxline(140, lpattern(solid) lcolor(gray)) \/\/\/ cutoff for systolic hypertension\nyline(140, lpattern(solid) lcolor(gray)) \/\/\/ ditto\ngraphregion(color(white)) ylabel(, grid glcolor(gs14)) \/\/\/ white background, light gray lines\nxlabel(90(20)170) ylabel(90(20)170) \/\/\/ where X and Y labels occur\naspectratio(1) \/\/ force figure to be a 1x1 square, not a rectangle\ngraph save 20_sbp_scatterplot_fit.gph, replace \/\/ need graph to merge later\ngraph export 20_sbp_scatterplot_fit.png, width(4000) replace\n\n***dbp\ntwoway (lfit ibp_dbp_pair average_dbp_omron_23, lcolor(gray) lpattern(dash) lwidth(vthick)) \/\/\/ \n(function y=x, ra(average_dbp_omron_23) clcolor(gs4)) \/\/\/\n(scatter ibp_dbp_pair average_dbp_omron_23, mcolor(black) msize(vsmall)), \/\/\/ \nlegend(off) \/\/\/\ntitle(\"Diastolic BP\", color(black)) \/\/\/\nytitle(\"\") \/\/\/\nxtitle(\"\") \/\/\/\nxline(90, lpattern(solid) lcolor(gray)) \/\/\/\nyline(90, lpattern(solid) lcolor(gray)) \/\/\/\ngraphregion(color(white)) ylabel(, grid glcolor(gs14)) \/\/\/\nxlabel(30(20)110) ylabel(30(20)110) \/\/\/\naspectratio(1)\ngraph save 21_dbp_scatterplot_fit.gph, replace\ngraph export 21_dbp_scatterplot_fit.png, width(4000) replace\n\n****combined scatterplot\ngraph combine 20_sbp_scatterplot_fit.gph 21_dbp_scatterplot_fit.gph, \/\/\/ \ngraphregion(color(white)) \/\/\/\nb1title(\"Standard (mmHg)\") \/\/\/\nl1title(\"IBP (mmHg)\") \/\/\/\nysize(3)\ngraph save combined_scatterplots_fit.gph, replace \/\/ \ngraph export combined_scatterplots_fit.png, width(4000) replace<\/pre>\n<p><\/p>\n<pre>***************************Bland-altman plots<br \/>***sbp\n***prep for figure\ngen mean_sbp_ave=(average_sbp_omron_23+ibp_sbp_pair)\/2 \/\/ this will be the x-axis\ngen diff_sbp_ave=ibp_sbp_pair-average_sbp_omron_23 \/\/ this will be y-axis\nsum diff_sbp_ave \/\/ this allows you to make a macro of the mean (\"r(mean)\") of the y axis variable\nglobal mean1=r(mean) \/\/ this saves the macro as mean1, to be called later\nglobal lowerCL1=r(mean) - 2*r(sd) \/\/ this saves a macro for the mean+2 times the SD (\"r(sd)\")\nglobal upperCL1=r(mean) + 2*r(sd)\n***make graph\ngraph twoway scatter diff_sbp_ave mean_sbp_ave, \/\/\/\nlegend(off) mcolor(black) \/\/\/\nytitle(\"\") \/\/\/ ytitle(\"Reference Minus Comparator (mmHg)\")\nxtitle(\"\") \/\/\/ xtitle(\"Average of Reference and Comparator (mmHg)\")\ntitle(\"Systolic BP\", color(black)) \/\/\/ \nyline($mean1, lpattern(shortdash) lcolor(gray)) \/\/\/ calls the macro from above\nyline($lowerCL1, lpattern(dash) lcolor(gray)) \/\/\/ ditto\nyline($upperCL1, lpattern(dash) lcolor(gray)) \/\/\/ \ngraphregion(color(white)) ylabel(, grid glcolor(gs14)) \/\/\/ white background\nylabel(-40(20)40) xlabel(90(20)170) \/\/\/ \naspectratio(1.08) \/\/ annoyingly, this wasn't a perfectly square figure so this line fixes it.\n***save graph\ngraph save 1_sbp_bland_altman_ave.gph, replace\ngraph export 1_sbp_bland_altman_ave.png, width(4000) replace\n\n***dbp\n***prep for figure\ngen mean_dbp_ave=(average_dbp_omron_23+ibp_dbp_pair)\/2\ngen diff_dbp_ave=ibp_dbp_pair-average_dbp_omron_23\nsum diff_dbp_ave\nglobal mean1=r(mean)\nglobal lowerCL1=r(mean) - 2*r(sd)\nglobal upperCL1=r(mean) + 2*r(sd)\n***make graph\ngraph twoway scatter diff_dbp_ave mean_dbp_ave, \/\/\/\nlegend(off) mcolor(black) \/\/\/\nytitle(\"\") \/\/\/ \nxtitle(\"\") \/\/\/\ntitle(\"Diastolic BP\", color(black)) \/\/\/ \nmsize(vsmall) \/\/\/\nyline($mean1, lpattern(shortdash) lcolor(gray)) \/\/\/\nyline($lowerCL1, lpattern(dash) lcolor(gray)) \/\/\/\nyline($upperCL1, lpattern(dash) lcolor(gray)) \/\/\/ \ngraphregion(color(white)) ylabel(, grid glcolor(gs14)) \/\/\/\nylabel(-40(20)40) xlabel(30(20)110) \/\/\/\naspectratio(1.08)\n***save graph\ngraph save 2_dbp_bland_altman_ave.gph, replace\ngraph export 2_dbp_bland_altman_ave.png, width(4000) replace\n\n***********combined image bland altman\ngraph combine 1_sbp_bland_altman_ave.gph pictures\/2_dbp_bland_altman_ave.gph, \/\/\/\nycommon \/\/\/ so the y axes are on the same scale \ngraphregion(color(white)) \/\/\/\nb1title(\"Average of IBP and Standard (mmHg)\") \/\/\/\nl1title(\"IBP Minus Standard (mmHg)\") \/\/\/\nysize(3)\ngraph save combined_dbp_sbp_ba.gph, replace \/\/ \ngraph export combined_dbp_sbp_ba.png, width(4000) replace<\/pre>","protected":false},"excerpt":{"rendered":"<p>NOTE: I have more recently put together user-friendly code on scatterplots and Bland-Altman plots. Go check those pages out. Scatterplots with a fitted line This is pretty straightforward in Stata. This is a variation of a figure that I made for a JAMA Internal Medicine paper. (I like to think that the original figure was &hellip; <a href=\"https:\/\/blog.uvm.edu\/tbplante\/2018\/07\/11\/making-scatterplots-and-bland-altman-plots-in-stata\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Making Scatterplots and Bland-Altman plots in Stata<\/span><\/a><\/p>\n","protected":false},"author":4473,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[477491],"tags":[],"class_list":["post-246","post","type-post","status-publish","format-standard","hentry","category-stata-code"],"_links":{"self":[{"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/posts\/246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/users\/4473"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/comments?post=246"}],"version-history":[{"count":8,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/posts\/246\/revisions"}],"predecessor-version":[{"id":1236,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/posts\/246\/revisions\/1236"}],"wp:attachment":[{"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/media?parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/categories?post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.uvm.edu\/tbplante\/wp-json\/wp\/v2\/tags?post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}