Skip to main content
v2026.11,610 entries · CC-BY 4.0

Scatterplots in Stata: twoway scatter and lfit Overlays

How to build a scatterplot in Stata with twoway scatter, add an lfit or qfit regression-line overlay, and combine multiple twoway elements in one graph command.

Ask about Scatterplots in Stata: twoway scatter and lfit Overlays

Answers are drawn from this guide and the rest of the CASRAI corpus, with a link to every source.

Answers are AI-generated from CASRAI’s own published pages and can be wrong, so check the linked sources before relying on one; your question is logged without personal data — never sold, never used to train a third-party model — to show us what CASRAI is missing, so please do not type personal or confidential details. How we use this

Written and maintained by CASRAI Editorial Board

Last updated

Stata builds scatterplots with the twoway scatter command, and adds a fitted regression line to the same graph by layering a second twoway element — lfit for a straight line, qfit for a quadratic curve — inside the same command rather than as a separate step. Because every twoway plot type follows the same building-block syntax, the pattern you learn for a scatter-plus-fit-line graph extends directly to combining any number of scatter, fit, and grouping elements in one call.

This page covers the graphing command itself: twoway scatter syntax, the lfit/qfit overlay, and combining multiple twoway elements. For the statistics behind the fitted line — ordinary least squares, residuals, and what a linear fit assumes about the data — see CASRAI’s regression analysis guide; for running the equivalent t-test procedure in Stata, see running a t-test in Stata, and for the software itself, see CASRAI’s SPSS overview and the R vs. Stata comparison if you’re deciding which package to learn.

The basic twoway scatter command

twoway is Stata’s general-purpose two-dimensional graphing command. Every plot it draws — scatter, line, bar, fitted curve — is a “plot type” specified as the first word after twoway, followed by a y-variable and an x-variable:

twoway scatter mpg weight

using Stata’s built-in auto dataset (sysuse auto) as a stand-in, this plots one point per observation, fuel economy (mpg) on the y-axis against vehicle weight (weight) on the x-axis. That two-variable, y-then-x argument order is the same for every plot type in the twoway family, which is what makes combining them predictable once you know the pattern.

Common scatter-level options control how the points look, not what’s plotted:

  • msymbol() — marker shape (circle, diamond, triangle, and so on)
  • mcolor() — marker color
  • msize() — marker size
  • mlabel(varname) — prints a text label next to each point, drawn from another variable (e.g. mlabel(make) to label each car by name)

These go inside the same command, after the variable list: twoway scatter mpg weight, mlabel(make) msymbol(oh).

Adding a fitted line: lfit and qfit

A raw scatterplot shows the relationship; a fit line summarizes it. Stata provides this as its own twoway plot type rather than a separate two-step process — you don’t need to run regress first. lfit fits a straight (linear, OLS) line across the range of the x-variable in your data; qfit fits a quadratic (curved) line by including a squared term internally. Both compute their own regression at graph time purely for plotting, and neither one saves new variables or estimation results to your dataset the way running regress separately would.

twoway lfit mpg weight
twoway qfit mpg weight

On their own, each of these draws only the fitted line with no points — useful for the syntax pattern, less useful as a finished graph. The overlay you actually want combines the fit line with the scatter of raw points in a single command (next section).

Two related plot types worth knowing:

  • lfitci / qfitci — the same fit, drawn with a shaded confidence-interval band around the line
  • lowess — a locally-weighted, non-parametric smooth rather than a single global line or curve, useful when you suspect the relationship isn’t well described by either a straight line or a simple quadratic

Choosing between lfit and qfit is a judgment call about the data, not a syntax question: lfit assumes a straight-line relationship; reach for qfit when the scatter visibly curves and a straight line would systematically miss the pattern at one or both ends of the range.

Combining multiple twoway elements in one graph command

This is the core mechanic: a single twoway command can layer any number of plot types by wrapping each one in parentheses, one after another, with no comma between the parenthesized groups. Stata draws them in the order listed, each on top of the last:

twoway (scatter mpg weight) (lfit mpg weight)

Each parenthesized element can carry its own options, scoped to just that element — for example, giving the scatter a marker style and the fit line a color, without one affecting the other:

twoway (scatter mpg weight, mcolor(gray)) (lfit mpg weight, lcolor(red))

Overall graph-level options — the ones that apply to the whole combined graph rather than to a single element, such as title(), ytitle(), xtitle(), legend(), or by() — go once, after a final comma, outside every parenthesized group:

twoway (scatter mpg weight) (lfit mpg weight), ///
    title("Fuel economy by weight") legend(order(1 "Observed" 2 "Linear fit"))

An older, equivalent syntax joins elements with a double pipe instead of parentheses (twoway scatter mpg weight || lfit mpg weight). It still works, but the parenthesized form is the clearer and more commonly taught style once options are attached to individual elements, since it’s unambiguous which options belong to which plot.

The same pattern scales past two elements. A scatter, a linear fit, and a confidence band together is simply three parenthesized groups in one command:

twoway (scatter mpg weight) (lfit mpg weight) (lfitci mpg weight)

Faceting with by(): one scatter-and-fit panel per group

by(groupvar) is also a graph-level option, so it goes after the final comma alongside title() and legend(). It splits the combined scatter-plus-fit graph into one small panel per value of a categorical variable, each panel with its own fitted line computed from just that group’s data:

twoway (scatter mpg weight) (lfit mpg weight), by(foreign)

This is the fastest way to check whether a relationship holds consistently across groups, or whether the fitted line for one subgroup looks meaningfully different from another — a visual companion to running the regression separately by group.

Saving or exporting the graph

Once a twoway command runs, the graph opens in Stata’s Graph window. Two commands turn it into a file:

  • graph export filename.png, replace — exports a static image (PNG, PDF, EPS, SVG, and others depending on platform) for a paper, slide deck, or report
  • graph save filename.gph, replace — saves it as a native Stata graph file, editable later in Stata’s own Graph Editor without re-running the command

Frequently asked questions

Does lfit require running regress first?

No. lfit (and qfit) compute their own regression internally, purely to draw the line — they don’t require a prior regress command and don’t leave estimation results behind the way regress does. If you already ran regress for the actual analysis and want the identical fitted line Stata used there, you can alternatively predict fitted values and plot them with twoway line, but for a quick visual overlay lfit/qfit is simpler and is what most Stata documentation and teaching materials use.

What’s the difference between lfit and qfit?

lfit draws a straight-line (linear) fit; qfit draws a curved (quadratic) fit by adding a squared term to the underlying regression. Use qfit when the scatter shows a visible curve that a straight line wouldn’t track well.

How do I label individual points on a Stata scatterplot?

Add mlabel(varname) to the scatter element, naming a variable that holds the text you want next to each point — for example mlabel(make) to label each observation by name. Combine with mlabpos() to control label placement relative to the marker.

Can I combine a scatterplot with more than one type of fit line?

Yes — add as many parenthesized elements as you need in the same twoway command, for example a scatter plus both an lfit and a qfit line, so you can visually compare a straight-line and a curved fit on the same graph.

How do I remove the legend or change its labels?

The legend() graph-level option, placed after the final comma, controls this: legend(off) removes it entirely, and legend(order(1 "label one" 2 "label two")) relabels and reorders the entries to match the order your parenthesized elements were listed in.

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Regulatory Radar

Stop finding out after the fact

$29/month, cancel anytime. Daily digest updates from our analysis, a dashboard holding the same items, and a cited assistant for everything they raise.

  • Federal Register, Federal Register+, Grants.gov, Regulations.gov, NSF News, UKRI, plus CASRAI’s own published content.
  • 44,322 indexed passages, and every answer cites the ones it drew on.