SPB Git forge

spb/wp4_uqo

Public
3commits 1branches 1releases
5.4 MBsize
maindefault branch
22 min agolast push
Python 64.6% TeX 23.3% HTML 11.6% Makefile 0.5%
9.9 KB

# 🛏️ Hedonic Pricing of Short-Term Rental Properties

UQO Working Paper No. 4 — A Multi-Method Analysis of Airbnb Listing Prices in Quebec

Paper Python Data Reproducible Institution Author

TL;DR — What determines the displayed nightly price of an Airbnb listing in Quebec? A province-wide scrape of 5,000 listing cards (3,456 priced) first has to be cleaned of a measurement defect: 26.5 % of "nightly" prices are multi-night stay totals (≈ 23 nights), detected and removed with a two-regime mixture of hedonic regressions (N = 2,480 nightly prices). On that sample a semi-log hedonic model with city fixed effects explains 51 % of log-price variance: capacity (guests, bathrooms, bedrooms), a shared bathroom (−32 %), photos, rating (+3.4 % per 0.1 point) and local density are the priced attributes; Superhost and Guest Favourite badges carry no premium. Implicit prices of rooms rise and those of reputation fall along the price distribution; spatial lag ρ̂ ≈ 0.20; gradient boosting adds ≈ 0.08 of out-of-sample R² (0.56 vs 0.47), with every model losing ≈ 0.07 when whole areas are held out.


# 📌 Status

Item Value
Version 1.1 (October 2026) — revised 2026-10-17 by the editorial-board review; v1.0 (May 2026) is tagged pre-revision-20261017
SSRN not yet submitted
Journal —
Code & data fully reproducible from data/processed/airbnb_clean_wp5.parquet + scripts/10_revision_reanalysis.py (≈ 10 min on an Apple-silicon laptop)

# 🎯 What this paper does

A listing card is a bundle of characteristics priced by its host. Following Rosen (1974) and Lancaster (1966), the paper estimates the hedonic price function

text
ln p_i = α + β_S' S_i + β_A' A_i + β_H' H_i + β_L' L_i + μ_c(i) + ε_i

(structural, presentation, host/reputation and location blocks plus city / spatial-cell fixed effects) by nested OLS with HC3 and clustered standard errors, re-estimates it at five quantiles, in spatial lag / error / Durbin form (ML, LeSage–Pace impacts) and against five machine-learning models under random and spatially blocked cross-validation (SHAP for the best). Before any of this, it diagnoses and models the stay-price contamination of the displayed price field.

# 🏆 Headline results (v1.1, N = 2,480 nightly-regime listings)

Object Estimate
Stay-price regime (mixture of regressions) 976 of 3,456 priced listings (28 %); δ̂ = 3.15 log points ≈ 23 nights; 7 ambiguous listings
Structural-only OLS (M1) R² = 0.443
Full hedonic model with city / cell FE (M5) R² = 0.509 (adj. 0.495), RMSE 0.475
Elasticities (M5, HC3 SE) guests 0.331 (0.037); ln(1+bathrooms) 0.437 (0.070); bedrooms 0.160 (0.042)
Shared bathroom −32 % (Kennedy-corrected)
Rating (rated listings) +0.337 per point (0.068) ≈ +3.4 % per 0.1
Superhost / Guest Favourite 0.023 (0.025) / −0.035 (0.027), not significant
Quantiles bedroom elasticity 0.01 (τ=0.10) → 0.19 (τ=0.90); ln reviews +0.042 → −0.042; pseudo-R² 0.28 → 0.41
Spatial Moran's I significant; ρ̂ = 0.200 (SAR), 0.261 (SDM); λ̂ = 0.284 (SEM); SAR multiplier 1.25
ML, random 5-fold CV XGBoost R² 0.559 / MdAPE 26.4 % vs OLS-M5 0.473 / 28.5 %
ML, spatially blocked CV XGBoost 0.483 vs OLS-M5 0.407

# 🗂 Repository layout

text
airbnb-listing-prices-hedonic/
├── data/
│   ├── raw/README.md                 # provenance; raw CSV not available
│   └── processed/airbnb_clean_wp5.parquet   # committed input (3,456 priced cards, from WP 5)
│       analysis_sample.csv           # written by the script (2,480 nightly-regime listings)
├── scripts/
│   ├── 10_revision_reanalysis.py     # ALL results of v1.1 (tables, figures, key numbers)
│   ├── 11_vif_table.py               # VIF appendix table from rev_key_numbers.json
│   ├── run_analysis.py, app.py       # v1.0 pipeline and dashboard (kept for the record; not used by v1.1)
├── src/                              # v1.0 package (kept for the record)
├── results/tables/rev_*.tex|json     # generated tables and key numbers (v1.1); other files = v1.0 artefacts
├── results/figures/, paper/figures/  # rev_fig_*.pdf (v1.1); 01–08 = v1.0 artefacts
├── docs/                             # REVIEW-REPORT.md, CHANGELOG-REVISION.md, main_pre-revision-20261017.pdf
└── paper/                            # main.tex + sections/ + references.bib → main.pdf

# 🚀 Quick start

bash
python3 -m pip install -r requirements.txt
python3 scripts/10_revision_reanalysis.py     # ≈ 10 min; writes results/tables/rev_* and paper/figures/rev_*
python3 scripts/11_vif_table.py
cd paper && make                               # latexmk → main.pdf

# 🗃 Data

Scrape of Airbnb search-result cards for Quebec, early 2026: 5,000 cards, 19 fields (title, city, property-type label, displayed price, rating, bedrooms, bathrooms, guests, amenity count, photos, reviews, Superhost, Guest Favourite, pets, coordinates). No room type, host ID, amenity list, cleaning fee or minimum stay. 1,544 cards have no price. The committed parquet is the WP 5 cleaned version of the 3,456 priced cards; the script parses the card title to recover the displayed star rating (456 unrated, 37 truncated), repairs 465 bathroom and 63 bedroom counts, recodes 161 studios, and classifies each card into the nightly or stay-price regime. See data/raw/README.md.

# 🔬 Methodology

  1. Price-regime diagnosis — marginal normal mixture of ln p; two-regime mixture of hedonic regressions (EM, common slopes, regime-specific intercept shift and variance, logistic regime equation); posterior < 0.5 defines the analysis sample.
  2. Nested OLS M1–M5 with HC3 and FE-group-clustered SEs; Kennedy (1981) premia; VIF; block F-tests.
  3. Quantile regression at τ ∈ {.10, .25, .50, .75, .90} with FE; paired bootstrap (B = 100) for τ=.90 − τ=.10 differences.
  4. Spatial econometrics — KNN (k = 5, 10) W on projected km; Moran's I; SAR/SEM/SDM by ML; LR test; LeSage–Pace impacts with simulated SEs.
  5. Machine learning — OLS, elastic net, random forest, gradient boosting, XGBoost, LightGBM; 5-fold random vs spatially blocked CV (20 blocks); R², RMSE, MAE (log), MdAPE (price); exact TreeSHAP for XGBoost.
  6. Robustness — regime cut-offs, $600/$1,000 rules, full sample, weighting by 1 − p̂, hotels excluded, rated only, Montreal vs outside, trimming, 60-cell FE.

# 🖼 Figures & tables inventory

File Content
rev_fig_logprice_mixture log-price histogram with the two mixture components
rev_fig_price_by_category price by title category (box plots)
rev_fig_map map of the analysis sample
rev_fig_partials binned partial residuals: distance to centre, rating
rev_fig_quantile quantile coefficients with 95 % bands
rev_fig_shap SHAP summary plot (XGBoost)

Tables (results/tables/rev_*.tex): price regimes, mixture, stay-regime logit, summary statistics, price by category, nested OLS, quantile, spatial models, impacts, ML cross-validation, SHAP importance, robustness, VIF. Key numbers quoted in the text: rev_key_numbers.json.

# ⚠️ Limitations

  • Displayed asking prices on one day, not transaction prices; cleaning fee unobserved; stay-regime listings cannot be converted to nightly prices (no stay length).
  • Single cross-section: no seasonality, no within-listing variation; estimates are conditional associations, not marginal willingness to pay.
  • No room type, host identifier or amenity list; the shared-bathroom flag and title category are the available proxies.
  • Scrape coverage reflects the platform's search on the collection dates; denser in urban and resort areas.

# 📝 Citation

bibtex
@techreport{boucher2026airbnbhedonic,
  author      = {Boucher, Simon-Pierre},
  title       = {Hedonic Pricing of Short-Term Rental Properties: A Multi-Method Analysis of Airbnb Listing Prices in Quebec},
  institution = {Universit\'e du Qu\'ebec en Outaouais, D\'epartement des sciences administratives},
  type        = {Working Paper},
  number      = {4},
  year        = {2026},
  month       = {October},
  note        = {Version 1.1}
}

# 👤 Author & contact

Simon-Pierre Boucher — Département des sciences administratives, Université du Québec en Outaouais (UQO), Gatineau, QC. 📧 simon-pierre.boucher@uqo.ca

# 🗒 Notes

  • Revision 2026-10-17 (v1.0 → v1.1): complete scientific revision by the editorial-board procedure; see docs/REVIEW-REPORT.md (diagnosis, verdicts, literature, maturity) and docs/CHANGELOG-REVISION.md (every change, old → new numbers, scripts, references). All v1.0 results were affected by a contaminated price field and several fabricated or mislabelled regressors; none is retained. The v1.0 PDF is docs/main_pre-revision-20261017.pdf.
  • Harmonised 2026-10-17: wp4/ → paper/, outputs/ → results/, scripts moved to scripts/; bibliography style aer.
  • Deviation from the standard layout: data/processed/airbnb_clean_wp5.parquet (227 KB) is committed because the raw CSV no longer exists anywhere; .gitignore carries the exception.