This repository contains two concise, self-contained reanalysis notebooks for the data from China's solar expansion policy reduces bird diversity.
01_replication_and_coefficient_reanalysis.ipynbreconstructs the released analysis results presented in the paper, reproduces the principal fixed-effects and instrumental variable estimates, decomposes the reported R-squared values, checks the PSI-to-area pathway.02_citizen_science_sampling_reanalysis.ipynbexamines the duration-per-observer variable, reporting discontinuities, sample inclusion, observer count, total observation time, sampling effort-adjusted outcomes, and IV sensitivity to observer count.
The notebooks have been executed from top to bottom and retain their outputs. Matching HTML exports are included for reading without Jupyter.
To see analysis and annotation, click on:
To read the comment manuscript (recommended), click and download:
Available at Zenodo: https://zenodo.org/records/22102223
Run the notebooks from this scripts/ folder. They read the adjacent ../DATA/ folder and import only the local helper modules listed below:
load_data.pybuilds the released analysis panel.regression_utils.pyfits the fixed-effects models with PyFixest.iv_observer_sensitivity.pyreproduces the IV model and observer-count sensitivity analysis.
The released data are read only; the notebooks do not modify files in ../DATA/.
-
Sampling effort is the central problem. Observed Shannon diversity reflects both the underlying bird community and the observation process. PSI is associated with sample inclusion, observer count, and total observation time. Adding observer count changes the fixed-effects estimate from −2.10% (P = 0.0006) to +0.58% (P = 0.288), reduces the IV estimate to near zero (P = 0.912), and strongly attenuates the richness association.
-
Poor data quality and erroneous preprocessing. Pooling checklists into county-month aggregates removes information on protocol, duration, distance, completeness, observer identity, and observer skill. The duration-per-observer variable also discards total sampling scale, while the released data contain implausible values, internal inconsistencies, and pronounced temporal shifts in coverage and reporting.
-
The proposed causal and mechanistic pathways are not supported. PSI is not associated with photovoltaic area under the study’s fixed-effects specification, the deployment-to-habitat link was not tested, and the photovoltaic-area and LAI associations with observed diversity disappear or remain nonsignificant after observer adjustment.
-
The reported high R² values are dominated by fixed effects. PSI partial R² is only 0.048% for Shannon diversity and 0.36%, 2.57%, and 0.75% for NDVI, nighttime lights, and LAI, respectively.
-
The released data cannot distinguish ecological change from changes in sampling coverage and detectability. Neither the original −2.10% estimate nor the observer-adjusted +0.58% estimate should be interpreted as the true ecological effect. Their sensitivity shows that the claimed negative causal effect is not identified by the released aggregates.
-
Causal claims from large observational datasets should be treated with caution. Statistical significance alone does not establish ecological importance or causal identification. Researchers applying methods to ecological data should collaborate closely with ecologists familiar with the data-generating and observation processes.
Python 3.11 was used for the saved results. From this folder, create an isolated environment and install the recorded dependencies with:
python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txtExecute both notebooks and retain the new outputs:
jupyter nbconvert --to notebook --execute --inplace 01_replication_and_coefficient_reanalysis.ipynb
jupyter nbconvert --to notebook --execute --inplace 02_citizen_science_sampling_reanalysis.ipynbRegenerate the readable HTML files after execution:
jupyter nbconvert --to html 01_replication_and_coefficient_reanalysis.ipynb
jupyter nbconvert --to html 02_citizen_science_sampling_reanalysis.ipynb- The principal models absorb county and exact year-month fixed effects and cluster standard errors by county.
- Fixed-effects OLS uses PyFixest's recursive singleton removal. The authors' IV code specifies Stata's
keepsingleton, so the IV reproduction usesfixef_rm="none". - The PyFixest small-sample correction is configured to match the released Stata specifications.

