Nighttime lights become a global income map — and reveal an N-shaped Kuznets curve
Nagoya University (GSID)
August 4, 2026
Act I
Every country reports one GDP number.
Almost none report the income of each province inside it.
That gap is invisible without subnational data.
Lessmann and Seidel (2017) use nighttime light as a stand-in for income.
Electricity, roads and activity all glow — so brightness tracks output where statistics do not.
Their pipeline, rebuilt here in Python end to end:
Act II
Mean regional Gini \(= 0.064\) (max \(0.163\)): most countries are internally fairly equal, with a long unequal tail.
\[y_r = \beta_0 + \beta_1 \ell_r + \beta_2 g_c + \gamma' X_r + \mu_g + \tau_s + \varepsilon_r\]
Everything except light is a control. The number we care about is \(\beta_1\).
0.102
random-effects light elasticity (col 7) · national-GDP elasticity \(= 0.889\) · matches the paper exactly
Predicted vs observed log regional GDP per capita, 5,258 region-years (\(r = 0.925\)). The fit holds from the poorest regions to the richest.
The calibration generalises across the whole income range, not one band.
Act II
\[\bar y = \frac{\sum_i w_i y_i}{\sum_i w_i}, \qquad p_i = \frac{w_i}{\sum_j w_j}, \qquad r_i = \frac{y_i}{\bar y}\]
One function turns a country’s regions into five indices — each region counting its people.
np.abs is the trap# --- Step 3b: the Gini = population-weighted average gap between people --
# y[:, None] - y[None, :] builds the full matrix of pairwise income gaps:
# entry (i, j) is yᵢ - yⱼ. np.abs makes them |yᵢ - yⱼ|; np.outer(w, w)
# weights each pair by both populations. Summing and normalising gives Gini.
gini = (np.abs(y[:, None] - y[None, :]) * np.outer(w, w)).sum() / (2 * sw**2 * mu)
return dict(GINIW=gini, GE_m1W=ge_m1, GE_0W=ge_0, GE_1W=ge_1, COVW=cv)Drop the absolute value and the Gini collapses to zero.
Population-weighted vs equal-weight Gini across country-years (corr \(= 0.75\)). Most points sit below the 45° line: weighting lowers measured inequality by \(0.0034\) on average.
Act II
\[\text{GINIW}_{ct} = \beta_1 \ln Y_{ct} + \beta_2 (\ln Y_{ct})^2 + \beta_3 (\ln Y_{ct})^3 + \alpha_c + \delta_t + u_{ct}\]
| Cubic term | Estimate | Sign |
|---|---|---|
| \(\beta_1\) (linear) | \(0.293\) | rises with early development |
| \(\beta_2\) (quadratic) | \(-0.032\) | then bends down |
| \(\beta_3\) (cubic) | \(0.001\) | faint upturn at the very top |
\(N = 879\), 180 countries, 5-year periods. Same sign pattern across all five indices — the N is not an artefact of the Gini.
Regional inequality (net of period effects) against log development, with the fitted cubic overlaid. The curve rises to a gentle peak near $3,000 per capita, declines through middle income, and ticks faintly upward at the top.
Up, then down, then faintly up — a description, not a policy lever.
Act II
0.071
ethnic-Gini coefficient (\(p < 0.001\), \(N = 844\)) · a \(0.1\) higher ethnic Gini implies \(+0.007\) regional Gini — about 11% of the \(0.064\) mean
| Determinant (on top of the cubic + FE) | Coefficient | Direction |
|---|---|---|
| Ethnic inequality | \(+0.071\) | concentrates |
| Resource rents | \(+0.018\) | concentrates |
| Aid / GDP | \(+0.015\) | concentrates |
| Trade openness | \(+0.005\) | concentrates |
| Arable-land share | \(-0.053\) | equalises |
Ethnic division concentrates; broad-based farming spreads.
Act III
Conley spatial-HAC standard errors for the clean light elasticity (\(\beta = 0.190\)). The interval widens with the radius; the estimate does not move.
| Inference | SE | \(t \approx\) |
|---|---|---|
| Naive (iid) | \(0.013\) | \(14\) |
| Conley 1,000 km | \(0.026\) | \(7\) |
| Conley 5,000 km | \(0.037\) | \(5\) |
The point estimate \(\beta = 0.190\) never moves; only the honest uncertainty grows.
Objection. You absorbed country and period effects and survived a spatial-HAC test — surely development causes this inequality path?
Response. No. Lights→GDP is a prediction model, not a structural one.
The Kuznets and determinant results are associations, not causal effects.
Predict income from light · weight by people · let the curve bend twice.