Stata Frames: Stop Saving and Re-Using Your Way Through Multi-Dataset Work
Stata 16's frames let you hold multiple datasets in memory and link them with frlink/frget instead of merge-and-save cycles. A worked example, plus the honest trade-offs.
30 Jun 2026, 12:48 UTC

If you've ever written save temp1, use otherfile, clear, merge, save temp2, use temp1 in a single do-file, you've felt the pain of Stata's classic one-dataset-in-memory model. Stata 16 introduced frames: named, independent datasets that all live in memory at once. The practical payoff is that you can keep a big reference file open in the background and pull only the variables you need into your working data — no temp files, no destructive merges.
This post walks through the core frame commands, a worked linking example with frlink and frget, and the honest trade-offs before you rewrite your workflow.
What a frame actually is
Think of each frame as its own complete Stata dataset — variables, observations, labels, and all — held under a name. Stata starts you in a frame called default. Everything you type still runs against the current frame; frames just let you have more than one dataset loaded and switch between them, or address another frame explicitly.
The essential commands:
frame create name— make a new empty frameframe change name— switch the current frameframe name: command— run one command against a frame without switchingframe copy source dest— duplicate a dataset into another frameframe drop name— remove a frame from memoryframes dir— list all loaded frames and their sizes
A quick sanity check at any point is frames dir, which shows you what exists and which frame is current. Get in the habit of running it in interactive sessions; it is the cheapest defense against the biggest frame-related mistake (more on that below).
A worked example: linking instead of merging
Say you have a large transactions file and a customer lookup table, and you want region and segment attached to each transaction for analysis. The classic approach is merge m:1 custid using customers.dta, which physically rewrites your working data. With frames, the lookup stays untouched in its own frame.
Run this in Stata 16 or later, in an interactive session or a do-file. No special permissions are needed; frames are in-memory only. Replace the file paths and variable names with your own.
version 16
* Working data stays in the default frame
use "transactions.dta", clear
* Load the lookup into its own frame
frame create customers
frame customers: use "customer_lookup.dta", clear
* Check the key before linking -- this step matters
frame customers: isid custid
* Link the frames on custid, then pull only what you need
frlink m:1 custid, frame(customers)
frget region segment, from(customers)
* Verify nothing unexpected happened
count
frames dirA few things to notice. First, isid custid confirms the key is unique in the lookup frame — if it fails, your link is not really many-to-one and you should stop and fix the data rather than proceed. Second, frlink creates a link variable in the working frame that points at the matching observation in customers; frget then copies just region and segment across. The source frame is never modified, and you never duplicated the whole lookup file into your analysis data.
To validate the result, compare against the old way: run the equivalent merge m:1 on a copy of the data and confirm the observation count and the distribution of region match. Unmatched keys behave differently in edge cases than you may expect from merge muscle memory, so check count if missing(region) and reconcile it against how many transactions genuinely lack a customer record.
Where frames genuinely help
The strongest case is memory efficiency with large reference data. If your lookup is 2 GB and your analysis needs three variables from it, copying those three variables via frget is far cheaper than materializing a merged file. The same logic applies to holding raw and cleaned versions of a dataset side by side, or keeping a "before" snapshot in a frame while you experiment with transformations you might throw away.
Frames also make exploratory work tidier. frame copy default scratch gives you a disposable playground; frame drop scratch cleans up without touching disk. Nothing hits the filesystem unless you explicitly save it — and note that frames live only for the current session unless you use frames save, so closing Stata loses them.
The trade-offs, honestly
The biggest risk is silent wrong-frame errors. Because every command runs against the current frame, an interactive session where you forgot you switched frames can produce perfectly plausible-looking output from the wrong dataset. There is no error message — just wrong results. Mitigations: prefer the frame name: prefix over frame change in do-files, and sprinkle frames dir into interactive work.
Second, compatibility. Frames require Stata 16 or later. Any do-file using them fails outright on Stata 15, which matters if you share code with collaborators, students, or replication archives. Put version 16 (or later) at the top of frame-based scripts so failures are loud and immediate rather than confusing.
Third, the ecosystem. Official Stata commands are frame-aware, but some older community-contributed ado files assume a single dataset in memory. If you mix frames with user-written commands, test on a small subset and verify results before trusting them at scale.
Where to start
Don't rewrite everything. Pick one recurring workflow — the one with the most save/use churn or the biggest merge — and convert it to a frame-based version. Run both side by side, compare counts and key summaries, and check help frame and help frlink in your installed Stata for the exact syntax your version supports. If the frame version is clearer and the numbers match, you have your template.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.