Street Trees 425 Inches Across: Impossible Diameters in Tree Census Data

On this page

Problem statement

Sort New York's street tree census by trunk diameter and the top of the list is impossible: a swamp white oak 425 inches across, a tulip tree of 389, a Callery pear β€” a small ornamental β€” of 298. The largest trees in the city's parks are a fraction of that. At the other end, 222 living trees have a diameter of zero. These are entry errors β€” a digit typed twice, a circumference recorded as a diameter, a missing value stored as 0 β€” and with 652,173 trees they are a small share, but they sit exactly where averages, maxima and biomass estimates are most sensitive.

This page finds them with species-specific limits, checks who recorded them, looks at rounding, and measures what they do to summary statistics.

Quick answer

Flag a diameter as suspect if it is zero, over 60 inches, or far beyond the upper quartile for its own species (more than five interquartile ranges above it):

alive = trees[trees.status == "Alive"].copy()
by_sp = alive.groupby("spc_common").tree_dbh
q = by_sp.transform(lambda s: s.quantile(0.75)); iqr = by_sp.transform(lambda s: s.quantile(0.75) - s.quantile(0.25))
alive["suspect"] = (alive.tree_dbh > q + 5 * iqr) | (alive.tree_dbh > 60) | (alive.tree_dbh == 0)
print(f"trees with a suspect diameter: {alive.suspect.sum():,} ({alive.suspect.mean():.2%})")
print(alive.nlargest(5, "tree_dbh")[["spc_common", "tree_dbh", "user_type", "borough"]].to_string(index=False))
trees with a suspect diameter: 1,403 (0.22%)
      spc_common  tree_dbh        user_type       borough
 swamp white oak       425  NYC Parks Staff      Brooklyn
    tulip-poplar       389  NYC Parks Staff        Queens
London planetree       318  NYC Parks Staff      Brooklyn
         pin oak       318 TreesCount Staff     Manhattan
    Callery pear       298 TreesCount Staff Staten Island

1,403 living trees, 0.22%, have a suspect diameter. The five largest are all over 24 feet across. Parks staff and census staff recorded the top five, not volunteers β€” the errors are not a volunteer problem.

Box plots of trunk diameter on a log scale for the ten commonest species, with whiskers at the 1st and 99th percentiles and red dots beyond; every species has outliers reaching far past its normal range, some at hundreds of inches. Box plots of trunk diameter on a log scale for the ten commonest species, with whiskers at the 1st and 99th percentiles and red dots beyond; every species has outliers reaching far past its normal range, some at hundreds of inches.
Diameter by species. What is impossible for a cherry is ordinary for a planetree.

Finding diameters that cannot be right

1. Look at both ends

print(alive.tree_dbh.describe(percentiles=[0.001, 0.5, 0.999]).round(1).to_string())
print(f"diameter 0: {(alive.tree_dbh == 0).sum():,}; over 60 inches: {(alive.tree_dbh > 60).sum():,}")
count    652173.0
mean         11.7
std           8.6
min           0.0
0.1%          1.0
50%          10.0
99.9%        47.0
max         425.0
diameter 0: 222; over 60 inches: 150

99.9% of living trees are 47 inches or less; above that the values jump to hundreds. 150 trees exceed 60 inches, a size almost no street tree reaches, and 222 are recorded as 0 although they are alive.

2. What is impossible depends on the species

lim = alive.groupby("spc_common").tree_dbh.agg(["median", lambda s: s.quantile(0.99), "max", "size"]).rename(columns={"<lambda_0>": "p99"})
print(lim[lim["size"] > 15000].round(0).to_string())
                   median   p99  max   size
spc_common                                 
Callery pear          8.0  21.0  298  58931
Japanese zelkova      6.0  23.0  210  29258
London planetree     22.0  41.0  318  87014
Norway maple         14.0  30.0  204  34189
Sophora               8.0  25.0  141  19338
cherry                5.0  18.0  291  29279
ginkgo                8.0  25.0  106  21024
green ash            13.0  30.0  159  16251
honeylocust          10.0  23.0  169  64263
littleleaf linden     9.0  29.0  266  29742
pin oak              17.0  40.0  318  53185
red maple            10.0  31.0  154  17246

A single cut-off would be wrong for most species. London planetrees and pin oaks grow large, with 99th percentiles of 41 and 40 inches; cherries and Callery pears stay small, at 18 and 21. A cherry of 291 inches is impossible by a factor of fifteen; a planetree of 60 might be real. The per-species rule scales the limit to each species' own spread.

3. Who recorded the extremes

print(pd.crosstab(alive.user_type, alive.suspect, normalize="index").round(4).to_string())
suspect            False   True 
user_type                       
NYC Parks Staff   0.9978  0.0022
TreesCount Staff  0.9981  0.0019
Volunteer         0.9975  0.0025

Suspect diameters are equally rare across recorders: 0.22% of Parks staff records, 0.19% of census staff records and 0.25% of volunteer records. Typing errors happen to everyone.

Histogram of trunk diameters on a log count scale from 0 to 425 inches, with flagged suspect values in red forming the whole far tail beyond about 60 inches. Histogram of trunk diameters on a log count scale from 0 to 425 inches, with flagged suspect values in red forming the whole far tail beyond about 60 inches.
The long tail of diameters and the values flagged as suspect.

4. Diameters cluster on round numbers

last = alive.tree_dbh[alive.tree_dbh.between(5, 40)] % 5
print("share ending in 0 or 5, inches 5-40:", f"{(last == 0).mean():.1%}", "(20% expected)")
print(alive[alive.tree_dbh.between(5, 40)].groupby("user_type").tree_dbh.apply(lambda s: (s % 5 == 0).mean()).round(3).to_dict())
share ending in 0 or 5, inches 5-40: 23.7% (20% expected)
{'NYC Parks Staff': 0.238, 'TreesCount Staff': 0.235, 'Volunteer': 0.238}

Between 5 and 40 inches, 23.7% of diameters end in 0 or 5 against the 20% expected if every inch were equally likely β€” a mild preference for round numbers, the same for all three recorder groups. It matters little for analysis but shows that diameters were sometimes estimated rather than measured with a tape.

What the errors cost

The data used on this page

New York City Department of Parks and Recreation, TreesCount! 2015 Street Tree Census on NYC Open Data: one row for every street tree, stump and dead tree mapped by staff and volunteers in 2015–2016, with species, trunk diameter, health and site conditions.

from pathlib import Path

import numpy as np
import pandas as pd
import requests

Path("data").mkdir(exist_ok=True)
SOCRATA = "https://data.cityofnewyork.us/api/views/{}/rows.csv?accessType=DOWNLOAD"
f = Path("data/nyc-street-tree-census-2015.csv")
if not f.exists():
    # TreesCount! 2015, the finished census (220 MB), NYC Open Data dataset uvpi-gqnh
    f.write_bytes(requests.get(SOCRATA.format("uvpi-gqnh"), timeout=1800).content)
trees = pd.read_csv(f, low_memory=False)
print(f"{len(trees):,} trees, {trees.status.eq('Alive').sum():,} alive")
683,788 trees, 652,173 alive

Example 1: what the outliers do to statistics

clean = alive[~alive.suspect]
print(f"mean DBH {alive.tree_dbh.mean():.2f} in raw, {clean.tree_dbh.mean():.2f} clean; median {alive.tree_dbh.median():.0f} both")
basal = lambda d: (np.pi * (d * 0.0254 / 2) ** 2).sum()
print(f"basal area, m2: raw {basal(alive.tree_dbh):,.0f}, clean {basal(clean.tree_dbh):,.0f} ({basal(clean.tree_dbh) / basal(alive.tree_dbh) - 1:+.1%})")
mean DBH 11.71 in raw, 11.67 clean; median 10 both
basal area, m2: raw 69,946, clean 68,075 (-2.7%)

Removing the suspect values moves the mean diameter only from 11.71 to 11.67 inches, and the median not at all. Basal area β€” the cross-sectional area of all trunks, which grows with the square of diameter and feeds biomass and canopy estimates β€” falls by 2.7%: a handful of trees recorded at hundreds of inches each count as much as several hundred normal ones.

Bar chart of the last digit of trunk diameters between 5 and 40 inches against a 10 percent line: digit 5 stands out well above the line. Bar chart of the last digit of trunk diameters between 5 and 40 inches against a 10 percent line: digit 5 stands out well above the line.
Heaping on round numbers in recorded diameters.

Example 2: the stumps carry their own column

st = trees[trees.status == "Stump"]
print(f"stumps: tree_dbh is {st.tree_dbh.eq(0).mean():.0%} zero; stump_diam median {st.stump_diam.median():.0f} in")
stumps: tree_dbh is 100% zero; stump_diam median 14 in

Stumps carry their size in a separate column: their tree_dbh is always zero and stump_diam holds a median 14 inches. Mixing the two columns, or including stumps in a living-tree summary, produces a different kind of impossible value.

Why diameters go wrong and how to catch them

Field data are typed by people in a hurry, often on a phone, and diameter is the field most exposed: a number, with no list to pick from, entered after a measurement. Doubling a digit, entering circumference instead of diameter (larger by a factor of about three), or leaving zero for unknown all produce values that are plausible as numbers and impossible as trees. Range checks at entry would catch most of them; once in the file, they need a rule.

The rule should reflect biology rather than statistics alone. A global percentile cut-off removes the genuinely big planetrees and keeps impossible cherries; a species-relative limit catches values that are extreme for that kind of tree. The flag should be kept as a column rather than the rows deleted, so that an analysis of large trees can inspect them, and so that the count of suspect values β€” here 0.22% β€” can be reported alongside the results.

Pitfalls with diameter data

  • Use species-specific limits. One threshold is wrong for both small and large species.
  • Zero means unknown for a living tree, not a seedling.
  • Squared quantities amplify errors. Basal area and biomass move most.
  • Stumps use stump_diam. Their tree_dbh is zero.
  • Flag, don't delete, and report how many were flagged.

FAQ

What is the largest street tree in New York's tree census?

The file's largest value, a 425-inch swamp white oak, is an entry error. 99.9% of living street trees measured 47 inches or less in 2015.

How should I clean tree diameter outliers?

Flag zeros, values above a hard ceiling, and values far beyond the species' own upper quartile; in New York's 2015 census that flags 1,403 trees, 0.22%.