SPB Git

spb/wp29_uqo

Public

# Does workforce training raise productivity growth? (F6-conf-04, simulated data)

# Question

What is the effect of one additional training hour per employee (programme year) on productivity growth in the following year, in percentage points per hour? Estimand: the causal coefficient on training_hours, assuming selection on observables given the pre-programme skill_index, and a linear, homogeneous effect. The data are simulated, not observed.

# Data and exclusions

data/firms.csv: 1200 firms (n_input_rows), 4 columns, no missing values and no duplicate firms. 12 rows had negative training_hours (n_excluded_negative_hours), which is physically impossible. I excluded them from the main analysis (out/exclusions.csv, step 2), leaving n_analysed = 1188. The excluded rows are kept in a sensitivity check. skill_index correlates strongly with both training (r = 0.69) and growth (r = −0.79), so it is a strong confounder (data_issues). Full audit: out/state/data_audit.md.

# Method

  • Baseline: OLS of productivity_growth on training_hours with an intercept, as the task specifies.
  • Target model: OLS of productivity_growth on training_hours + skill_index. skill_index is measured the year before the programme, so it is a valid pre-treatment control and not a mediator. It is the only covariate available, so selection on observables means conditioning on it.
  • Standard errors: heteroskedasticity-robust (HC1) for every model (effect_se_type), with 95% normal-approximation intervals.
  • Fit metric: RMSE = sqrt(mean(e²)) of the in-sample residuals.
  • Sensitivity checks: (a) a cubic polynomial in skill_index, to probe whether the linear adjustment is misspecified; (b) all 1200 rows, including the negative-hour rows.
  • No randomness is used (random_seed = null).
  • Outputs: out/table1.csv and out/figure1.png are produced by out/analysis.py.

# Results

  • Unadjusted association: −0.132 pp per hour (naive_estimate), 95% CI [−0.160, −0.103] (naive_ci_low, naive_ci_high). RMSE 3.86 pp (baseline_metric).
  • Adjusted effect (estimand): +0.254 pp per hour (effect_estimate), 95% CI [0.234, 0.273] (effect_ci_low, effect_ci_high). RMSE 1.98 pp (model_metric). R² rises from 0.07 (naive_r2) to 0.76 (adjusted_r2).
  • Skill coefficient: −4.62 pp per index unit (skill_index_coefficient).
  • Sign reversal: the sign flips from negative to positive once skill is controlled. Higher-skill firms received more training but grew more slowly, so the unadjusted slope is confounded downward. The omitted-variable-bias identity holds exactly in the sample (out/state/checks.md).
  • Conclusion code: positive_effect (conclusion), because the whole 95% interval lies above zero.
  • Robustness: the cubic-skill specification gives 0.254 (sensitivity_cubic_skill_estimate). The full 1200-row sample gives 0.252 (sensitivity_fullsample_effect_estimate). Both fall inside the main interval.

# Uncertainty

  • The HC1 SE is 0.0098 (effect_se), almost the same as the conventional SE of 0.0098 (effect_se_conventional). So there is little sign of heteroskedasticity.
  • The 95% CI has a half-width of about 0.019 pp per hour, which only covers sampling uncertainty.
  • It does not cover uncertainty about the identifying assumption (no unobserved confounding) or about the functional form beyond the cubic check. Those are the larger risks, discussed below.

# Limitations and open issues

  • Main threat – unobserved confounding. The causal reading depends entirely on skill_index being the only confounder. Anything else that drives both training uptake and growth would bias the estimate: management quality, sector, firm size, credit constraints, or anticipated demand shocks. The file has no other variables, so this cannot be tested. The large shift from the naive to the adjusted estimate shows how sensitive the result is to which confounders are included. I did not run a formal sensitivity analysis for unobserved confounding (e.g. Oster/Cinelli–Hazlett bounds).
  • Measurement error in skill_index. If the index measures true skill with noise, controlling for it removes only part of the confounding. Because skill pushes growth down and training up, residual confounding would bias the estimate downward, but the size of that bias is unknown.
  • Functional form and homogeneity. I assumed a linear, homogeneous effect. I only checked a cubic in skill (exploration also tried a training×skill interaction, which was small and not significant; it is not reported as a result). I did not test nonlinearity in hours, such as diminishing returns. A heterogeneous effect would make the coefficient a variance-weighted average, not the average treatment effect (ATE).
  • Negative training hours. These 12 rows suggest the data-generating process was not truncated at zero, or that recording errors exist. Excluding them barely changes the estimate (sensitivity_fullsample_effect_estimate). However, if the treatment variable has errors, other values could be wrong too, which I cannot check.
  • Not checked: spillovers between firms, attrition or survivorship (only firms with observed growth appear), external validity beyond simulated data, and out-of-sample predictive fit (both RMSEs are in-sample).
  • What would invalidate the result: an unobserved confounder correlated with training conditional on skill; skill_index actually being measured after training started (the task states it is pre-programme); or outcome timing that overlaps the programme year.
Files · 452964ee0fbbaa40fbbed2c87a54ca798ffd6a85
Menu

Theme