# F1-dev-01 — Analytic firm dataset and revenue aggregates ## Question Build a documented, analysis-ready, one-row-per-firm version of the synthetic firm cross-section `data/firms.csv`. Then report: the number of distinct firms; the mean and median revenue (millions USD) over firms with known revenue; and the mean head count over all distinct firms. ## Data and exclusions The file has 445 data rows (`n_input_rows`). I found three issues, all listed in `data_issues`: 1. **Duplicate rows.** 45 rows are exact duplicates of another row (`n_exact_duplicate_rows`). I checked that no firm_id appears with conflicting values, so I kept the first copy. This leaves 400 distinct firms (`n_unique_firms`). 2. **Mixed units.** 60 distinct firms report revenue in USD_thousands (`n_thousands_unit_firms`); the rest report in USD_millions. I converted all revenue to millions USD. 3. **Missing revenue.** 6 distinct firms have an empty revenue cell (`n_missing_revenue`): F0048, F0121, F0129, F0269, F0348, F0399. They are dropped from the revenue aggregates and from `analytic.csv`, but kept for `mean_employees`. The ledger in `out/exclusions.csv` runs 445 → 400 (duplicates) → 400 (unit conversion) → 394 (missing revenue). So `n_analysed` = 394, and 445 − 45 − 6 = 394. ## Method This is a deterministic cleaning pipeline (`out/analysis.py`), applied in this order: drop exact duplicates; convert units (USD_thousands × 10⁻³); drop rows with missing revenue (complete cases, no imputation). The script stops with an error if it finds conflicting duplicates or an unknown unit. No randomness is involved (`random_seed` = null). ## Results | quantity | value | key | |---|---|---| | distinct firms | 400 | `n_unique_firms` | | firms with missing revenue | 6 | `n_missing_revenue` | | firms analysed | 394 | `n_analysed` | | mean revenue (M USD) | 249.962 | `mean_revenue_musd` | | median revenue (M USD) | 162.306 | `median_revenue_musd` | | mean employees (all 400 firms) | 1101.435 | `mean_employees` | | naïve raw mean of `revenue` (mixed units, with duplicates) | 30695.88 | `mean_revenue_raw` | The naïve baseline (`mean_revenue_raw`) is about 120 times the cleaned mean (`mean_revenue_musd`). Almost all of that gap comes from leaving the USD_thousands rows unconverted. The mean is well above the median, so the revenue distribution is right-skewed. ## Uncertainty The aggregates are descriptive statistics of the file itself, not estimates for a wider population. If the 394 firms are treated as a sample, the standard deviation of revenue is 274.30 M USD (`sd_revenue_musd`) and the standard error of the mean is 13.82 M USD (`se_mean_revenue_musd`). ## Limitations and open issues - The data are simulated. The cleaning trusts the `unit` column on each row; I did not try to detect unit errors beyond that, although converted values fall in a plausible range (5.7–2057.6 M USD). - Firms with missing revenue are excluded rather than imputed. If revenue is not missing at random, the revenue aggregates could be biased; with only 6 of 400 firms affected, the effect is small. - `mean_employees` covers all 400 distinct firms, including the 6 with missing revenue, as the task specifies. It is not computed over the analytic dataset. - The task was completed in full (`feasibility` = "complete").