Pump Neighborhoods




John Snow actually published two versions of the cholera map. The first, which appeared in On The Mode Of Communication Of Cholera (Snow 1855a), is the more famous. The second, which appeared in the Report On The Cholera Outbreak In The Parish Of St. James, Westminster, During The Autumn Of 1854 (Snow 1855b), is the more important. What makes it important is that Snow adds a graphical annotation that outlines the neighborhood around the Broad Street pump, the set of addresses that he contends is most likely to use the pump:

By identifying the pump’s neighborhood, Snow sets limits on where we should and where we should not find fatalities. Ideally, this would help support his claims that cholera is a waterborne disease and that the Broad Street pump is the source of the outbreak. Looking at the second map Snow writes: “it will be observed that the deaths either very much diminish, or cease altogether, at every point where it becomes decidedly nearer to send to another pump than to the one in Broad street” (Snow 1855b, 109).

To help assess whether the map supports Snow’s arguments, I provide functions that allow you to analyze and visualize two flavors of pump neighborhoods: Voronoi tessellation, which is based on the Euclidean distance between pumps, and walking distance, which is based on the paths traveled along the roads of Soho. In either case, the guiding principle is the same: all else being equal, people will choose the closest pump.

Voronoi tessellation

Cliff and Haggett (1988) appear to be the first to use Voronoi tessellation1 to compute pump neighborhoods. In their digitization of Snow’s map, they include coordinates for 13 Voronoi cells. These are available in HistData::Snow.polygons. To replicate their effort, I use deldir::deldir(). With the exception of the border between the neighborhoods of the Market Place and the Adam and Eve Court pumps (pumps #1 and #2), I find that Dodson and Tobler’s computation are otherwise identical to those using ‘deldir’.

To explore the data using this approach, you can use neighborhoodVoronoi() to create scenarios of different sets of neighborhoods based on the pumps you select. The figure below plots the 321 fatality “addresses” and the Voronoi cells for the 13 pumps in the original map.

The next figure plots the same data but excludes the Broad Street pump from consideration.

In either case, the numerical results can be summarized using the print() method.

To get an estimate of the difference between observed and expected fatalities, you can use pearsonResiduals(). Note that “Pearson” is “Count” minus “Expected” divided by the square root of “Expected”:

Walking distance

The obvious criticism against using Voronoi tessellation to analyze Snow’s map is that the neighborhoods it describes are based solely on the Euclidean distance between water pumps. Roads and buildings don’t matter. In this view of the world, people walk to water pumps in perfect straight line fashion rather than along the twists and turns of paths created by having to follow roads and streets.

Not only is this unrealistic, it’s also contrary to how Snow thought about the problem. Snow’s graphical annotation appears to be based on a computation of walking distance. He writes: “The inner dotted line on the map shews [sic] the various points which have been found by careful measurement to be at an equal distance by the nearest road from the pump in Broad Street and the surrounding pumps …” (Report On The Cholera Outbreak In The Parish Of St. James, Westminster, During The Autumn Of 1854, p. 109.).

While the details of his computations seem to be lost to history, I replicate and extend his efforts by writing functions that allow you to compute and visualize pump neighborhoods based on walking distance.2 My implementation works by transforming the roads on the map into a network graph and turning the computation of walking distance into a graph theory problem. For each case (observed or simulated), I compute the shortest path, weighted by the length of roads, to the nearest pump. Then, by drawing the unique paths for all cases, a pump’s neighborhood emerges:

The summary results are:

“Expected” walking neighborhoods

To get a sense of the full range of a walking neighborhood or of the “expected” neighborhood, I apply the approach above to simulated data. Using sp::spsample() and sp::Polygon(), I place 20,000 regularly spaced points, which lie approximately 6 meters apart, unitMeter(dist(regular.cases[1:2, ])), across the map and then compute the shortest path to the nearest pump.3

I visualize the results in two ways. In the first, I identify neighborhoods by coloring roads.4

In the second, I identify neighborhoods by coloring regions using points() or polygon().5 The points() approach, shown below, is faster and more robust.

Exploring scenarios

Beyond comparing methods (e.g., walking v. Euclidean distance), you can explore different scenarios. For example, Snow argues that residents found the water from the Carnaby and Little Marlborough Street pump (#6) to be of low quality and actually preferred to go to the Broad Street pump (#7).6 Using this package, you can explore this and other possibilities by selecting or excluding pumps: