Privacy and preparation
Missing values in a dataset: classify them, then accept, fix or reject
By SourceX Editorial · Reviewed by Noah Loul ·
Short answer
Missing values in a dataset are fields with no usable value, including blanks hidden as placeholders like 0, N/A or 1900-01-01. Classify each gap by why it is missing: not applicable, never captured, lost in export, redacted, a system default or not yet arrived. Accept gaps that carry no bias, fix what the supplier can re-export, and reject or renegotiate when data quality gaps hit labels or key fields in ways tied to outcomes.
Key takeaways
- Count every encoding of missing, including 0, N/A, 1900-01-01 and picklist defaults, before computing any null rate.
- MCAR, MAR and MNAR describe the mechanism, but the cause in the source system or export is what tells you what to do.
- Six operational causes cover most gaps: not applicable, never captured, lost in export, redacted, system default and late-arriving.
- Decide per field and per use; a small gap in a label can matter more than a large gap in an optional input.
- Export losses and late-arriving fields are usually fixable by the supplier; never-captured values can only be documented.
- Set field-level acceptance criteria before delivery so renegotiation is about a stated test.
What counts as a missing value in a business dataset?#
A missing value is any field where the record has no usable observation, whether it arrives as a true null, an empty string, or a placeholder that looks like data such as 0, N/A or 1900-01-01. In operational exports the placeholders usually outnumber the real nulls. Tooling will not catch them all: pandas read_csv converts empty strings and tokens such as N/A and NULL on load, but not 0, sentinel dates or picklist defaults. Build a missingness dictionary of every encoding per field before computing any null rate; the per-field counting method is Stage 3 of the guide to validation checks for structured dataset deliveries.
MCAR, MAR and MNAR: what do the types of missing data tell a buyer?#
The classic types describe why data is missing relative to the values themselves: missing completely at random (MCAR), missing at random given observed fields (MAR), and missing not at random (MNAR), where the chance of being missing depends on the unobserved value. Rubin's 1976 Biometrika paper set out when the missingness process can be ignored, and Little and Rubin's textbook covers the three mechanisms and sensitivity analysis.
MCAR means the gaps are a random subset, so dropping incomplete rows loses volume but adds no bias. MAR means missingness depends on something you can see, for example satisfaction scores missing more often for tickets closed by email than by chat, so you can model around it if that field is in the data. MNAR means the gap is related to the missing value itself, for example deal-loss reasons left blank most often on the deals that were lost badly.
Little's 1988 test is a global test of MCAR across all fields, and a significant result is evidence against MCAR. No test on the observed data can prove MAR over MNAR, because the evidence you would need is exactly what is missing. That is why the useful question for a licensed dataset is operational, not statistical: what in the source system or the export produced this gap? The supplier usually knows the answer, and the answer tells you which mechanism you are dealing with.
- 01Your work records
- 02Personal details removed
- 03You approve the release
- 04Licensed to AI developers
What are the types of missing data in operational records?#
Operational records have six recurring causes of missingness, and each one maps to a different review decision. The classic mechanisms still apply underneath, but naming the cause is what lets you decide and ask the supplier the right question.
| Missingness type | What it means | Typical example | Usual mechanism |
|---|---|---|---|
| Structurally not applicable | The field cannot have a value for this record type or stage | Closed-lost reason on an open opportunity; parts cost on a remote-only service call | Not missing data at all if documented; becomes MAR if confused with real gaps |
| Never captured | The field existed but users skipped it, or it was added to the system later | Industry field blank on accounts created before it became required; free-text resolution notes left empty | Often MAR (by era, team or channel), sometimes MNAR (skipped on bad outcomes) |
| Lost in export | The value exists in the source system but did not survive extraction | Custom fields missing from a report-based export; attachments or comments not included; truncated long text | Usually systematic by field or object, independent of the value |
| Redacted or withheld | The value was deliberately removed for privacy, confidentiality or scope | Customer names masked; contract values withheld; free text with personal data removed | Deliberate and documented; can be MNAR if redaction rules key on content |
| System-default placeholder | A default or sentinel stands in for no value and looks like real data | Priority Normal on every imported ticket; created date 1900-01-01; amount 0; country set to the company's home country | Hidden missingness; behaves like the type it masks but inflates apparent completeness |
| Late-arriving | The value is filled in after the export cutoff | Resolution date and CSAT empty on recently opened tickets; invoice paid date blank on recent invoices | Depends on record age; creates right-censoring near the end of the window |
How do you detect each kind of missingness?#
Measure per-field null rates first, using Stage 3 of the guide to validation checks for structured dataset deliveries, then look for the signature of each cause. Not-applicable gaps are near 100 percent null for one record type and near 0 for another; never-captured gaps step at a date, team or channel; export losses show fields null on every row or text lengths clustered at one maximum (Excel caps a cell at 32,767 characters). Redaction leaves consistent mask tokens or empty columns that the data dictionary lists; defaults show as one value far above its neighbors on migrated rows; late-arriving gaps grow as record age falls. The decision table below pairs each signature with its decision.
What does a field-level missingness profile look like?#
The base per-field profile, with null rates and known defects, is covered in what a dataset quality report should contain. A buyer adds two columns to it: the classified missingness type and the decision. The example below is a hypothetical support-ticket extract of about 120,000 tickets over three years; the numbers are invented to illustrate the method. A raw null rate alone would have passed created_at and priority as complete and flagged parts_cost as a problem when it is mostly structural.
| Field | Classified type | Decision |
|---|---|---|
| ticket_id | Complete (0% null) | Accept |
| created_at | System-default placeholder: 3.8% set to 1900-01-01, all on tickets migrated from the prior helpdesk | Fix: ask supplier for original dates or a migration flag; exclude from time-based splits until resolved |
| priority | System-default placeholder: 61% Normal on migrated tickets versus 34% on native tickets | Accept with flag: add an is_migrated indicator and do not train priority prediction on migrated rows |
| resolution_code | Never captured (MAR by team) plus late-arriving on open tickets (9% null) | Accept if open tickets are excluded and per-team rates are documented |
| resolution_notes | Never captured, concentrated on escalated tickets (22% null) | Renegotiate: notes are the training signal and the gap is tied to outcome |
| csat_score | Never captured (survey not sent on all channels) and likely MNAR (71% null) | Accept for training, reject as an evaluation label without a response-bias analysis |
| parts_cost | Structurally not applicable on remote tickets (58% null) | Accept: recode as not applicable for remote tickets, re-measure on onsite tickets only |
| customer_name | Redacted (masked token on every row) | Accept: expected under the de-identification scope; confirm a stable pseudonymous customer key exists |
How do you decide whether missing values are acceptable, fixable or grounds to reject?#
Decide per field and per use: a gap is acceptable when it carries no bias for the task, fixable when the supplier can recover or document it, and grounds to reject or renegotiate when it removes the signal you are paying for or hides a bias you cannot correct. The table maps each missingness type to the decision and the question to send the supplier.
| Missingness type | How to detect it | Risk to training and evaluation | Default decision | What to ask the supplier |
|---|---|---|---|---|
| Structurally not applicable | Null rate cross-tabbed by status, stage or record type | Low if recoded; high if a model learns not applicable as a negative signal | Accept and recode to an explicit not-applicable value | Which record types or stages never populate this field? |
| Never captured | Null rate by created month, team and channel; step changes at dates | Biased coverage by era or team; MNAR if skipped on bad outcomes | Accept if MAR and documented; renegotiate if the field is a label or core input | When did this field become available or required, and which teams used it? |
| Lost in export | Field null on all rows, truncation at round lengths, counts below the source system | Silent loss of the most valuable content, often long text and attachments | Fix: require a re-export before acceptance | Which export method was used, and can custom fields, full text and related objects be included? |
| Redacted or withheld | Mask tokens, hashes, empty columns listed in the data dictionary | Low if a stable pseudonymous key survives; high if redaction removed joins or labels | Accept if within agreed scope; renegotiate if redaction removed in-scope signal | What are the redaction rules, and which keys remain stable across tables? |
| System-default placeholder | Top-value frequency per field; spikes on migrated or imported rows | Fake completeness; models learn the default as real behavior | Fix: recode to missing and add an indicator; reject if it masks most of a key field | Which fields have defaults, and which records were migrated or bulk-imported? |
| Late-arriving | Completeness of outcome fields by record age | Right-censoring biases outcome rates and inflates open-case share near the cutoff | Accept with an exclusion window, or fix with a later refresh | What is the typical lag before this field is filled, and can a refreshed cut be delivered? |
When should missing data lead you to reject or renegotiate a dataset?#
Reject or renegotiate when the missingness hits the labels, outcomes or text you are buying the dataset for, or is concentrated in the cases the model most needs; a dataset can be 95 percent complete and unusable if the missing 5 percent is every escalation. Four patterns justify reopening terms: an MNAR target the supplier cannot explain, export loss of content the agreement described, placeholders masking most of a delivered field, and segment-concentrated gaps that break stated coverage. Renegotiation usually means a re-export, a refreshed cut, a narrower priced scope or documentation, with per-field acceptance criteria agreed before delivery. For ticket-specific cases, see missing timestamps and broken threads as fixable problems versus deal breakers.
How should you handle missing data you decide to keep?#
Recode first, then choose between excluding rows, imputing values, or letting the model handle missingness natively, and always keep a record of which values were filled. Recoding means turning every placeholder into a real missing value and every structurally not-applicable gap into an explicit category, so the next steps see the true pattern.
For simple numeric and categorical fields, scikit-learn's SimpleImputer fills with the mean, median, most frequent value or a constant, and its add_indicator option, or the separate MissingIndicator, keeps a binary flag so the model can still use the fact that a value was missing. IterativeImputer models each field from the others but is documented as experimental in current stable releases (through 1.9), with an API that may change. Histogram-based gradient boosting in scikit-learn handles missing values natively by learning which branch they follow at each split.
Fit any imputer on the training split only and apply it to validation and test data, otherwise statistics from evaluation data leak into training. Do not impute labels or evaluation targets; drop or hold out those rows and report the exclusion. For MNAR fields, no imputation method removes the bias on its own, which is why sensitivity analysis, which Little and Rubin cover for MNAR models, is the honest response: show how results change under different assumptions about the missing values.
What should you ask a data supplier about missing values before signing?#
Ask for a field-level data dictionary that states what an empty value means for each field, plus the export method, redaction rules and known defaults. Datasheets for Datasets frames the same idea as a standard question: is any information missing from individual instances, and if so, why (for example, because it was unavailable)? Its wording notes that this does not include intentionally removed information but might include, for example, redacted text.
When you source operational records through SourceX, datasets are sourced on request from U.S. businesses rather than held in stock, and the request form is where you state scope, volume, format, timing and licensing needs, so field-level completeness expectations can be part of the request from the start. Under SourceX's standing terms, de-identification is performed by SourceX directly or through its processing partner, which is why redacted fields should be expected and specified, not discovered on delivery.
Remember that a completeness agreement is not a rights agreement. Whether a supplier may license the records, and whether de-identified data can be used for your purpose, are separate questions for the licensing terms and counsel.
- Which fields are mandatory in the source system, and since when?
- What does an empty value mean in each field: not applicable, unknown, not yet filled, or removed?
- Which export method, API or report produced the file, and what does it exclude?
- Which records were migrated or bulk-imported, and what defaults did that process apply?
- What are the redaction rules, and which identifiers remain stable after de-identification?
- How long after record creation are outcome fields typically filled?
Frequently asked questions
What are the three types of missing data?
The three classic types are missing completely at random (MCAR), missing at random (MAR) and missing not at random (MNAR). MCAR gaps are unrelated to any data, MAR gaps depend on other observed fields, and MNAR gaps depend on the missing value itself. The framework comes from Rubin's 1976 Biometrika paper and is covered in Little and Rubin's textbook.
How do you tell whether data is MCAR, MAR or MNAR?
Little's MCAR test is a global test that can give evidence against MCAR, and cross-tabs of null rates against other fields show MAR dependencies. MNAR cannot be confirmed from the observed data alone. In business records, asking the supplier how the field is populated is usually the fastest way to identify the mechanism.
What percentage of missing data is acceptable?
There is no universal threshold. A field that is 70 percent empty can be acceptable as an optional input if the gap is unbiased, while a label that is 5 percent empty can be disqualifying if the missing rows are the hardest cases. Set acceptance criteria per field, based on how the field is used.
Should I delete rows with missing values or impute them?
Deleting rows is reasonable when gaps are close to MCAR and you can afford the lost volume. Imputation keeps rows but should be fit on training data only and paired with a missingness indicator. Never impute a label or evaluation target; exclude those rows and report the exclusion.
Are placeholder values like 0 or N/A missing data?
Yes, when they stand in for no observation. Numeric and date sentinels like 0, -1 and 1900-01-01 stay as values in pandas unless you recode them, so a field can look complete while being largely empty. Classify each one by cause, then decide whether to accept, fix or reject.
Can a supplier fix missing values after delivery?
Often, if the gap came from the export rather than the source system. Lost custom fields, truncated text and missing related records can usually be recovered with a different export, and late-arriving outcomes can be filled with a refreshed cut. Values that were never captured cannot be recovered, only documented.
Sources
- Rubin (1976), Inference and Missing Data, Biometrika 63(3):581-592, shows that the process that caused missing data can be ignored for sampling-distribution inference under missing-at-random conditions, though inferences are conditional on the observed missingness pattern. Source
- Little and Rubin, Statistical Analysis with Missing Data, 3rd edition (Wiley, 2019), covers missing-data mechanisms, complete-case analysis, missing-not-at-random models and sensitivity analysis. Source
- Little (1988), A Test of Missing Completely at Random for Multivariate Data with Missing Values, JASA 83(404):1198-1202, proposes a single global test statistic for MCAR; a significant result is evidence against MCAR. Source
- pandas uses different sentinel values to represent missing values depending on data type, such as NaN for NumPy float types, NaT for datetimes and NA for nullable dtypes. Source
- pandas.read_csv treats empty strings and tokens such as 'N/A', 'n/a', 'NA', 'NULL', 'null', 'NaN' and 'None' as missing by default (the pandas 1.5 list omitted 'None'); extra markers can be added with na_values and the defaults switched off with keep_default_na=False. Source
- scikit-learn's SimpleImputer fills missing values with the column mean or median (numeric only), the most frequent value, or a supplied constant, and add_indicator=True appends missing-value indicator columns. Source
- scikit-learn's MissingIndicator produces binary indicators for missing values so the missingness pattern can be kept as model input alongside imputed values. Source
- scikit-learn's IterativeImputer is documented as experimental through release 1.9: predictions and API might change without a deprecation cycle, and it is enabled with enable_iterative_imputer. The 1.10 dev docs say it is no longer experimental. Source
- scikit-learn's HistGradientBoostingClassifier supports missing values natively, learning at each split whether samples with missing values go to the left or right child. Source
- Datasheets for Datasets (Gebru et al.) proposes a documentation template whose composition questions ask whether any information is missing from individual instances and, if so, why (e.g. because it was unavailable); the question excludes intentionally removed information but may include, for example, redacted text. Source
- Microsoft's Excel specifications and limits page lists the total number of characters that a cell can contain as 32,767. Source
Related resources
Tell us what data you need
Share scope, volume, format, timing and licensing needs. Datasets are sourced on request.