Published November 2026 · 11 min read
How to Automatically Code Open-Ended Responses in Stata: .dta In, .dta Out
Stata is excellent at everything that happens after a variable is numeric. Open-ended survey answers are not numeric. They sit in a str or strL variable, and the usual options are a wall of strpos() rules or an export to Excel for hand-coding that strips your labels on the way back. This tutorial shows a third option: upload the .dta, approve a codeframe, and get the same .dta back with labelled 0/1 category variables you can drop straight into tabstat, logit or mrtab.
Sample files for this tutorial
A fictional library patron survey with 240 respondents, labelled categorical variables and two open-ended string variables.
- library_survey_2026.dta — uncoded input
- library_survey_2026_coded.dta — an example of the coded output, in the structure SurveyCat returns
The Input: What's in the .dta
Run use library_survey_2026.dta, clear and describe, and you will see this structure:
| Variable | Kind | Value label | Variable label |
|---|---|---|---|
| resp_id | numeric | Respondent ID | |
| branch | numeric | 1 Central … 4 Westgate | Branch visited most often |
| age_group | numeric | 1 18-29 … 99 Prefer not to say | Age group |
| satisfaction | numeric | 1 Very dissatisfied … 5 Very satisfied | Overall satisfaction with the library |
| q_improve | string | What one thing would most improve your library? | |
| q_reason | string | Why did you give that rating? |
The Do-It-Yourself Approach, and Where It Breaks
Most Stata users start with pattern matching:
gen txt = lower(q_improve)
gen byte hours = strpos(txt, "hour") | strpos(txt, "close") | strpos(txt, "open")
gen byte quiet = ustrregexm(txt, "quiet|silent")
gen byte parking = strpos(txt, "park") > 0
Then you list q_improve if hours, and the trouble starts:
- "The car park closes before the library does" matches both
hoursandparking. It is about parking. - "Stay open past 6pm so I can come after work" is caught only because you added
open, and that same stem will catch "open-plan seating" or "more open space" in the next survey. - "It gets very noisy after school" never says "quiet", so the quiet-space flag misses it.
Each fix adds another clause, and the rule set only works for this one question. It is also hard to defend in a methods section: "we flagged answers containing 'close'" invites the obvious follow-up question.
The AI-Assisted Workflow
- Upload the .dta (up to 20 MB). Variable labels and value labels are read along with the data.
- Pick the string variables to code. The picker shows each variable's label and a sample answer. Add a line of context per question if it helps ("library patrons; keep building issues separate from digital services").
- Get a proposed codeframe. The AI reads up to 200 answers and suggests four to seven non-overlapping categories (5 credits per question on packs, included on monthly plans). Or skip that step for free and type the codeframe you already have.
- Edit and approve it. Rename, merge, split, delete, or ask AI refine to rework it. The order you leave them in is the order of the output variables.
- Classification runs in the background at 1 credit per non-empty answer. Blank answers are free. An answer can get more than one code.
- Check and edit the codes. Flagged low-confidence answers come first, and you can recode one response or a filtered group in one step. Edits go straight into the .dta, and a review log records AI vs. final codes.
- Download
updated_library_survey_2026.dta.
The Output: New Variables in the Same .dta
Open library_survey_2026_coded.dta and describe q_improve_c01-q_improve_none:
| Variable | Values | Variable label |
|---|---|---|
| q_improve_c01 | 0 No / 1 Yes | What one thing would most improve your library?: Longer opening hours |
| q_improve_c02 | 0 No / 1 Yes | …: More books and new titles |
| q_improve_c03 | 0 No / 1 Yes | …: Quieter study space |
| q_improve_c04 | 0 No / 1 Yes | …: Better Wi-Fi and computers |
| q_improve_c05 | 0 No / 1 Yes | …: More events and activities |
| q_improve_c06 | 0 No / 1 Yes | …: Parking and access |
| q_improve_none | 0 No / 1 Yes | …: none of the above |
- Names fit Stata's rules. They are built from your variable name plus
_c01,_c02… and stay inside the 32-character limit. A long source name is shortened, and clashes with existing variables are avoided. The category text lives in the variable label. - Consecutive and numbered, so varlist ranges like
q_improve_c01-q_improve_c06and wildcards likeq_improve_c*work. - Labels carry over. Every original variable keeps its variable label and value label.
q_improve_noneis 1 for answers that fit no category and for blank answers. Restrict toq_improve != ""when you want "% of those who answered".
A Do-File for the Coded Data
use "updated_library_survey_2026.dta", clear
* Stata has no user-missing values: turn 99 (Prefer not to say) into .a
mvdecode age_group, mv(99=.a)
* Share of respondents (who answered) mentioning each theme
summarize q_improve_c01-q_improve_c06 if q_improve != ""
* Theme shares by branch
tabstat q_improve_c01-q_improve_c06 if q_improve != "", ///
by(branch) statistics(mean) format(%4.2f)
* One multiple-response table (user-written: ssc install mrtab)
mrtab q_improve_c01-q_improve_c06 if q_improve != ""
* Do people who want better Wi-Fi rate the library lower?
regress satisfaction i.q_improve_c04 i.branch if q_improve != ""
* Read the verbatims behind a code before you report it
list resp_id q_improve if q_improve_c04 == 1, noobs clean
The tabstat line on the sample file gives the share of answering respondents in each branch who raised each theme:
| Theme | Central | Northside | Riverside | Westgate |
|---|---|---|---|---|
| c01 Opening hours | 0.30 | 0.24 | 0.20 | 0.24 |
| c02 Books and titles | 0.18 | 0.10 | 0.05 | 0.12 |
| c03 Quiet space | 0.24 | 0.16 | 0.27 | 0.20 |
| c04 Wi-Fi and computers | 0.14 | 0.29 | 0.27 | 0.29 |
| c05 Events | 0.18 | 0.14 | 0.20 | 0.09 |
| c06 Parking and access | 0.22 | 0.24 | 0.23 | 0.12 |
Central patrons are the ones asking for longer hours. The other three branches have a Wi-Fi and computers problem. That is the kind of finding the open-ended question exists to surface, and it took one line of Stata once the coding was done. (Branch subsamples here are small, so treat it as an illustration, not a significance test.)
Making It Reproducible
Stata users care about reproducibility, and AI coding raises fair questions. Three habits answer most of them:
- Save the codeframe with the project. Keep the approved category list (in order) in your project folder next to the do-file. On Research Pro it can be saved as a versioned codebook and loaded into the next run in one click.
- Keep the coded .dta as a frozen input. Treat
updated_*.dtalike raw data. Every downstream step lives in the do-file. - Report a validation check. Hand-code a random subsample (
sample 60, counton a copy) and report agreement with the AI codes. Typical agreement is typically 85–95% agreement with human coders, depending on how clear your categories are.
Frequently Asked Questions
Does it work with strL variables and long answers?
Yes. Any string variable can be coded. Answers longer than 5,000 characters are truncated before classification, which in practice only affects essay-length responses.
Can I code several open-ended variables in one go?
Yes. Select them all. Each gets its own codeframe and its own block of _c01… variables.
What does a typical study cost?
1 credit = one classified response to one question. A 1,000-respondent survey with two open ends is about 2,000 credits. Packs start at $25 for 850 credits, and monthly plans start at $100 for 4,000 credits. 80 free credits come with every new account.
The short version
Replace fragile strpos() rules with an AI pass over a codeframe you approve. Upload the .dta, download the .dta with labelled _c01… variables, and analyze with the commands you already use.
Try It on the Sample .dta
80 free credits, no credit card. Upload the sample, then your own data.
Start Free →The SurveyCat Team
SurveyCat is a self-serve verbatim coding tool for researchers, analysts and agencies. It reads and writes Stata, SPSS, Excel and CSV so coding fits the workflow you already have.