When Absence Is Not Evidence: Reading Empty Results Correctly

When Absence Is Not Evidence: Reading Empty Results Correctly

E
By Etzal Earth
13 min read

A query returns an empty array. No hospitals inside the polygon, no pharmacies on the street, no buildings in the block. The response came back fast, the status code was 200, and nothing about it resembles a failure. The natural reading is that there is nothing there.

That reading is wrong far more often than most teams assume. An empty result is a statement about a dataset, not a statement about the world. The distance between those two statements is where a large share of bad spatial analysis lives, and it is a distance that widens quietly, because nothing in the response draws attention to it.

Real decisions get made on top of these empties. A coverage score reads zero clinics as a service desert. A risk model reads no recorded flood as a safe site. A routing tool reads an absent road as an impassable one. Each of those conclusions might be correct. Each might also be an artefact of a survey that never happened.

Two different claims wearing the same clothes

There are two distinct propositions here, and one representation serving both of them.

The first proposition is that the feature does not exist at that location. The second is that the feature was not recorded in this dataset for that location. The first is a claim about the world, and asserting it honestly requires evidence that somebody looked. The second is a claim about a file, and it requires no evidence beyond the file itself.

An empty array expresses the second while being read as the first. Nothing in the array distinguishes them, because an array has no room for the distinction. The information needed to tell them apart, whether any survey covered this area, at what resolution, and how recently, sits outside the response entirely, usually in a documentation page that the calling code has never read and never will.

There is an old name for the move from the second claim to the first: arguing from ignorance. It is not always invalid. If a thorough search was performed, and that search would reliably have found the thing had it been present, then absence genuinely is evidence of absence, and the strength of that evidence scales with the thoroughness of the search. The error is not in making the inference at all. The error is in making it without knowing whether the search ever took place.

Why spatial data is unusually good at hiding this

Several properties of geographic data conspire to make this trap easier to fall into than it is in almost any other domain.

Spatial queries are always bounded. Every request carries a bounding box, a radius, a polygon, or an administrative code, and the bound is chosen by the caller rather than by the data. A query against a region the dataset never covered looks identical to a query against a region the dataset covered thoroughly and found empty. Both come back with the same shape and the same length.

Coverage is not uniform, and it is almost never documented per cell. A national dataset is rarely national in the sense of having been surveyed evenly across a nation. It is a mosaic of local mapping efforts, contributor enthusiasm, procurement cycles, and whatever imagery happened to be cloud free. The metadata then describes that mosaic as a single object with a single date and a single description.

Feature density varies by orders of magnitude across space regardless of data quality. A genuinely empty square kilometre is completely ordinary. Because real emptiness is so common, artificial emptiness raises no suspicion at all.

Finally, rendering hides it. A map draws what exists. There is no visual difference between an area with nothing in it and an area that nobody has mapped. The reader resolves the second into the first, confidently, in well under a second, and then reasons from a picture that was never claiming what it appeared to claim.

The four ways a result becomes empty

Empties arrive by different routes, and the routes call for different responses, which is the practical reason not to collapse them into one concept called missing data.

Nobody surveyed it. This is the most common cause and the least visible. In contributed data, coverage follows contributors. In official data, coverage follows budgets and legal mandates. Neither follows the distribution of what is actually on the ground. A district can be absent from a building dataset not because it lacks buildings but because it lacked a mapping campaign.

The survey ran, but the feature fell below a detection threshold. Anything derived from imagery or remote sensing has a floor, and everything under the floor is systematically absent rather than randomly absent. This deserves its own treatment and gets it below.

A filter removed it. This cause is self inflicted, which also makes it the most fixable. A query that filters on a category value, an operator name, an opening hours field, or a minimum area silently drops every record whose field is null, so records with unknown values behave exactly like records that failed the test. A filter for buildings above a certain floor area removes buildings whose area was never recorded, and unrecorded attributes cluster in exactly the places where the attribute survey was thinnest.

The request failed and the failure was swallowed. A timeout caught in a broad exception handler, an upstream error mapped to an empty list because that kept the page from breaking, a tile that never loaded. These produce the most dangerous empties, because they are unrelated to geography and therefore leave no pattern an analyst could notice.

Missing survey means widening the query or finding another source. A detection floor means changing instrument or accepting the floor explicitly. A filter artefact means fixing the query, usually by handling nulls as a third branch rather than a false. A swallowed failure means retrying, and above all not caching the result.

Detection thresholds put the small things systematically out of reach

Every observing system has a smallest thing it can see, and that limit is a property of the instrument rather than of the world.

Satellite imagery at ten metre resolution cannot resolve a market stall. A building footprint model trained to find rectangular roofs will miss the informal structure with an irregular tarpaulin over it. A vehicle detector tuned to avoid false positives will drop the ambiguous cases, and ambiguous usually means small, partly shaded, or partly hidden under a tree. A night lights product has a radiance floor, below which a settlement reads as unlit rather than as dim.

The consequence is not that some things are missing. The consequence is that specific kinds of things are missing, and they are the same kinds every time. Small, informal, temporary, and irregular features fall out. Large, permanent, regular, and formally constructed ones survive. A dataset produced this way is not a noisy sample of reality. It is a clean sample of one part of reality, and it will read as complete because nothing in it is wrong. An analysis that counts economic activity from detected buildings understates places where that activity happens in structures the detector was never going to find, and it understates them in a way that correlates with the thing being measured.

The honest response is to publish the floor. If a product cannot see structures under a certain footprint area, or activity under a certain radiance, then that limit belongs in the response next to the count, in the same units as the count. It converts a false zero into a true statement: no features above the detection floor were found here.

How a zero becomes a confident total

Absence has a compounding property that few other data quality problems share. It survives aggregation, and it gains authority on the way through.

Take a count of some feature per district, summed to a regional or national figure. Surveyed districts contribute real counts. Unsurveyed districts contribute zero, because zero is what an empty result becomes as soon as it meets a sum. The total is a plain number. It carries no error bar, no coverage note, and no indication that some of its inputs were silence rather than measurement. It is indistinguishable from a total computed over complete data.

Then it acquires a denominator. Facilities per capita, per square kilometre, per household. Now it is a rate, and rates invite comparison, and comparison is usually the entire reason the figure was requested. The unsurveyed district ranks worst, lands at the top of a priority list or the bottom of a ranking, and a decision follows from its position.

The direction of the resulting error is the part that should worry anyone building on top of this. Unsurveyed places tend to be the poorer, the more remote, the more recently built, or the more politically marginal ones. The artificial zeros are therefore not scattered at random. They cluster where reality was already hardest to observe, and they push every derived figure in a consistent direction. That is bias, not noise, and aggregation does nothing to it. Averaging shrinks variance. It leaves a systematic shift exactly where it was.

Propagating nulls instead of zeros is the textbook defence, and it is worth being blunt about why it loses: a null total is useless to whoever asked for the total, so the pressure to substitute zero comes from the consumer rather than the producer, and it usually wins. A workable middle position is to compute the figure over the covered area only, report the covered fraction alongside it, and refuse to publish at all when coverage falls below a threshold agreed in advance. That gives the consumer a number, keeps the number honest about its own basis, and puts the decision to ignore the caveat where it belongs.

Detecting the empties you cannot see

Data quality work usually means checking that present values are right. Absence requires the opposite habit: looking for the places where nothing is present and asking whether that is plausible.

A few checks find most of it.

  • Density discontinuities at administrative boundaries. Real feature density changes gradually across space. When density drops sharply along a district or national border, the cause is almost always a change in data provenance rather than a change in the world.
  • Comparison against an independent source with different failure modes. Population grids, night lights, road length, and imagery all imply the presence of built environment. If a district has roads and lights and people but no buildings in the building layer, the building layer is wrong, not the district.
  • Manual sampling against imagery. Tedious and irreplaceable. Pick a dozen cells that came back empty, look at recent imagery, and count what is actually there. The result is the closest thing to a measured false negative rate a team is likely to get.

None of these prove that a specific empty is wrong. They identify where to spend attention, which is what a quality process is for.

Designing systems where absence carries its reason

The general principle is short: an empty result should be a structured object, not an empty container.

At minimum, a response that returns nothing should also return what was searched, how thoroughly, and why the caller got nothing. In practice that means a small set of fields alongside the result, and the set does not need to be elaborate:

  • The status of the search itself, distinguishing at least searched and found nothing, not searched here, searched below the relevant threshold, filtered out, and upstream failure.
  • The extent actually searched, which is not always the extent requested. When a source covers only part of a requested bounding box, the response should say which part, so the caller can decide whether the answer applies to the question.
  • The observation basis: which source answered, when it was collected, and at what resolution or minimum mapping unit.
  • The detection floor, where one exists, expressed in the same units as the thing being counted.

This matters more for machine callers than for human ones. A human analyst may carry context about a source being thin in a region and hedge accordingly. A model calling an API knows only what the response contains. If the response contains nothing, the model reports nothing, in the fluent unhedged register that language models produce by default. The response is the only place the caveat can be attached, because it is the only place the caller is guaranteed to look.

The cache is where a temporary absence becomes permanent

Caching turns a momentary failure into a lasting fact, which makes it a separate hazard rather than an implementation detail. An upstream source is briefly unavailable, the handler returns an empty list, the cache stores it under a normal time to live, and every caller for the rest of that window receives an authoritative empty. If the cache is warmed ahead of demand, nobody observes the original failure at all. If the cached value then feeds a derived table, a tile set, or a precomputed score, the absence outlives the entry that created it.

Three rules prevent most of this. Never cache a result whose provenance includes a failure, even a partial one. Give negative results a shorter lifetime than positive ones, since an empty is more likely to be an error than a populated result is. Tag cached empties with their reason, so a later reader can tell a real empty from a stored failure without re running the query.

Writing not determined when a number would be more convenient

The last part is cultural rather than technical, and it is the part that decides whether any of the above survives contact with a deadline.

Every pipeline has a point where a value is unavailable and a number is required. A dashboard cell needs filling. A schema declares the field non nullable. A downstream model does not accept nulls. A stakeholder asked for a figure and will read a blank as incompetence rather than as honesty. Zero fits in all of those places and asks nothing of anybody.

Writing not determined costs something real. It makes a product look less complete, it prompts questions, and it occasionally means saying that the analysis someone paid for cannot answer the question they asked in the region they care about. The discipline is to pay that cost anyway, because the alternative is not a slightly worse number. The alternative is a confident wrong number that nobody will revisit, because nothing about it looks like it needs revisiting.

A working rule for the boundary: a figure may be reported as zero only when the process that produced it can state what it looked at and why it would have found the thing had it been present. When that statement cannot be made, the correct output is not determined, whatever shape the schema prefers. The schema is easier to change than the decision that gets made downstream.