# Methodology — "The Horniest Cabinet in History" ## 1. Cabinet list - Source of truth: the GOV.UK content API for the ministers page (`https://www.gov.uk/api/content/government/ministers`), the machine-readable version of https://www.gov.uk/government/ministers. - Pulled: **2026-07-21 12:22 UTC** (gov.uk page last updated 2026-07-21 13:14 BST). Appointments were still ongoing on 20–21 July 2026; the pipeline is re-runnable and will pick up changes on the next run. - We include the 23 people gov.uk lists under "Cabinet ministers" (`ordered_cabinet_ministers`). Ministers who "also attend Cabinet" are excluded. One member (Baroness Smith of Basildon) sits in the Lords. - Where gov.uk still showed a member's pre-reshuffle post alongside the new one (a normal transition artifact), we used the most recently started current role. - Cross-checked against news coverage of 20–21 July 2026 (ITV News, LabourList live blog); no discrepancies. ## 2. Member identification - IDs resolved via the UK Parliament Members API (`https://members-api.parliament.uk/api/Members/Search`), disambiguated by party (Labour / Labour Co-op), current membership and house. - Service history from `/api/Members/History?ids=…`: every Commons/Lords membership period, first election, and gaps > 90 days. - **Years in Parliament** = the sum of all membership periods (both houses) up to 21 July 2026. Dissolution periods (~5 weeks per election) are excluded for everyone, so the denominator treats all members equally. Notable gaps the metric corrects for: - Andy Burnham: out of the Commons 3 May 2017 → 18 Jun 2026 (Mayor of Greater Manchester; re-entered at the Makerfield by-election on 18 Jun 2026 per the Members API). - Heidi Alexander: 9 May 2018 → 4 Jul 2024 (Deputy Mayor of London). - Douglas Alexander: 30 Mar 2015 → 4 Jul 2024 (lost seat). - Baroness Smith: Commons 1997–2010 as Angela Smith (Basildon), Lords 2010–present; both houses counted. ## 3. Hansard searching - Source: the official Hansard API (`https://hansard-api.parliament.uk`), endpoint `/search/contributions/Spoken.json`, parameters `queryParameters.searchTerm`, `.memberId`, `.startDate`, `.endDate`, `.orderBy=SittingDateAsc`, `.skip`, `.take=100`. Spoken contributions only — no written questions/answers. - Searches run: **21 July 2026, 12:30-14:30 UTC**. All raw responses cached to disk (`raw_responses/`); the run is reproducible without re-fetching. - The API's result-count fields (`SpokenResultCount`) are broken (always 0), so we paginated every query until a short page. - **The search engine does not stem**: "nipple" and "nipples" are different queries. Every term was searched as an explicit variant set (see table below); multi-word variants were sent as quoted phrases. Every hit was then re-verified against a word-boundary regex on the contribution text; API hits that failed regex verification are kept in the dataset flagged `unverified` and excluded from all counts. - **Pre-2005 records are unattributed in the API** (MemberId = −1; speaker is a free-text `AttributedTo` string). Member-filtered searches therefore only reliably cover ~2005 onwards. To cover older service (five cabinet members were first elected 1992–2001), we additionally swept every term unfiltered across **9 Apr 1992 – 31 Dec 2005** (window starts at the earliest first election in the cabinet: Angela Eagle) and attributed hits by matching the `AttributedTo` string against each member's names-over-time and constituency history from the Members API, validated against their service dates. Matches are labelled by confidence (`name+seat`, `name_only`, `seat_only`); ambiguous matches were dropped and counted in the QA log, not silently. - Overlap between the sweep and member-filtered queries is deduplicated on `ContributionExtId` per (member, term). - Politeness: single-threaded, ≥0.4 s between requests, retry with backoff. ### Term variants searched | Term | Tier | Search variants | |---|---|---| | viagra | 1 | viagra, viagras | | orgasm | 1 | orgasm, orgasms, orgasmic | | brothel | 1 | brothel, brothels | | dogging | 1 | dogging | | threesome | 1 | threesome, threesomes | | erectile | 1 | erectile | | libido | 1 | libido, libidos | | aphrodisiac | 1 | aphrodisiac, aphrodisiacs | | foreplay | 1 | foreplay | | nipple | 1 | nipple, nipples | | g-spot | 1 | "g-spot", "g spot" | | kama sutra | 1 | "kama sutra", kamasutra | | strip club | 1 | "strip club", "strip clubs" | | lap dance | 1 | "lap dance", "lap dances", "lap dancing", "lap dancer", "lap dancers", "lap-dancing" | | sex toy | 1 | "sex toy", "sex toys" | | onlyfans | 1 | onlyfans | | blue balls | 1 | "blue balls" | | gigolo | 1 | gigolo, gigolos | | dominatrix | 1 | dominatrix, dominatrixes, dominatrices | | chastity | 1 | chastity | | erection | 2 | erection, erections | | intercourse | 2 | intercourse | | climax | 2 | climax, climaxes | | stimulation | 2 | stimulation | | bondage | 2 | bondage | | missionary | 2 | missionary, missionaries | | prostitute | 2 | prostitute, prostitutes | | escort | 2 | escort, escorts | | frenulum | 2 | frenulum | | rectum | 2 | rectum, rectums | | genitals | 2 | genitals | | member | 2 (gag) | count-only via /search.json overview | - **"member" (Tier 2 gag)**: searching this per-member and harvesting text is infeasible (it appears in a large share of all parliamentary speech — "the hon. Member for…"). We report, per member, the number of **spoken contributions containing the word "member"** from the Hansard overview endpoint (`/search.json`, `TotalContributions`). It is a count of contributions, not occurrences, covers only the attributed era (~2005+), and is reported as its own column, outside the leaderboard score. - Deliberate scope choices, for transparency: "lap dance" was expanded to include "lap dancing/dancer(s)" (the form Parliament actually uses, e.g. licensing debates); "prostitute" does **not** include "prostitution"; "escort" does not include the verb forms "escorted/escorting"; "genitals" does not include "genitalia"; "orgasm" includes "orgasmic". ## 4. Counting and cleaning - The headline unit is **mentions** (occurrences of the term in the text of a spoken contribution), not contributions; a speech using "brothel" three times counts three. Contribution counts are also reported. - Deduplication: unique on (member, term, ContributionExtId). - **Tier 2 classification**: every hit was classified by a rule-based context pass over a ±150-character window around each occurrence: - *escort*: false positive if police/prison/military/naval/convoy/patient transport context; relevant if escort agency/service, sex-work context. - *erection*: false positive for erection of buildings/statues/masts etc.; relevant for erectile/penile/sexual context. - *intercourse*: false positive for social/commercial/diplomatic intercourse (common in older debates); relevant for sexual intercourse. - *stimulation*: false positive for economic/fiscal/nerve/brain etc. - *climax*: false positive for "climax of the debate/campaign" metaphors. - *bondage*: false positive for debt bondage/bonded labour/slavery. - *missionary*: false positive for religious context; relevant only for "missionary position"/sexual context. - *prostitute*: relevant by default (it is literally sex-related); false positive only for the "prostituting a principle" metaphor. - *frenulum, rectum, genitals*: always relevant (anatomical — the gag). - Rows matching neither direction are flagged **review** for manual checking. **Nothing is deleted**: every row keeps its classification and the dataset reports raw vs cleaned counts side by side. - **Tier 1 caveat we discovered and did not hide**: "dogging" is *not* unambiguous in parliamentary English — "problems dogging the industry" is a routine metaphor. "Chastity" also occasionally appears as fiscal metaphor. Both received the same context classification as Tier 2 terms; Tier 1 totals exclude their false positives, and raw Tier 1 counts are reported alongside. - Mentions occurring inside what looks like a quoted **legislation title** are flagged (`in_legislation_title`) and kept, per the editorial rule: exclude only if misleading, otherwise footnote. ## 5. Scores - `tier1_mentions` — cleaned Tier 1 mentions (all service, both eras). - `tier2_cleaned_mentions` — Tier 2 raw minus rule-classified false positives (review-flagged rows are **included**, so manual review can only lower these counts; the review column is published). - `combined_score` = tier1 + tier2 cleaned. - **`mentions_per_year`** (headline) = combined_score / years in Parliament. - The "member" contribution counts are a separate gag column, not scored. ## 6. Known caveats 1. **Departmental brief inflation.** Ministers answering on Health, Home Office, Justice, Care or Women & Equalities briefs discuss sexual-health and sex-industry policy as their job. The leaderboard column `relevant_briefs_held` (from the Members API biography endpoint) lists every such post per member with dates — disclose alongside the ranking. This materially affects, above all, **the leaderboard winner**: every one of Alan Campbell's 46 cleaned mentions dates from 2008–10, when he was the Home Office minister (Crime Reduction) taking the Policing and Crime Bill — lap-dancing club licensing and prostitution offences — through the Commons. Also relevant: Burnham (Health Secretary 2009–10, earlier Health minister), Cooper (Home Secretary 2024–25, now Health), Streeting (Health Secretary 2024–26), Kinnock (Care Minister 2024–26), Mahmood (Home Secretary 2025–, Justice 2024–25), Norris (Home Office 2025–26), Eagle (Home Office minister twice), and Phillipson (Women & Equalities 2024–). 2. **Attribution era asymmetry.** Post-2005 coverage is exact (member-ID-filtered). 1992–2005 coverage relies on text attribution of the sweep; it is high-precision but could miss oddly formatted attributions, so pre-2005 counts are a floor. This mainly concerns Eagle, Cooper, Healey, Campbell, D. Alexander, Bryant, Burnham and Baroness Smith. 3. **Occurrence counting is text-based** on the API's contribution text; column-number markup was stripped before counting. 4. **Contribution ≠ utterance**: Hansard is the edited official record. 5. **The "member" gag count** covers ~2005+ only and counts contributions, not occurrences (see §3). 6. **Link checking**: all data came from the Hansard API (hansard-api.parliament.uk), which is unrestricted. The public website the quote links point to (hansard.parliament.uk) blocks requests from the data-collection server (CDN bot protection, HTTP 403), so the links could not be click-tested from here. However, every debate GUID used in top_quotes.md was verified against the API's /debates/debate/{id}.json endpoint and matches the linked title and date exactly; the URLs follow Hansard's canonical pattern. A quick click-through in an ordinary browser before print is still recommended. 7. Hansard content is used under the **Open Parliament Licence v3.0**; quotes carry attribution and links. ## 7. Fallback - TheyWorkForYou was held in reserve; the official Hansard API worked for every member, so **no member's data comes from TheyWorkForYou**. ## 8. Data quality log - Total unique (member, term, contribution) hits: **66** (38 relevant, 28 false positives — all retained and flagged in contributions.csv; 0 unresolved 'review' rows: every rule-flagged row was hand-adjudicated, see manual_classifications.json). - 11 rows hand-adjudicated after rule flagging; 2 pre-2005 rows hand-attributed from surname-only follow-up lines and 5 rejected (manual_attributions.json — includes two 'Lord Burnham' rows that are a hereditary peer, not Andy Burnham, and two 'Mr. Smith' rows that are John Smith and Chris Smith). - 2,815 unfiltered 1992-2005 sweep rows scanned; 3 attributable to current cabinet members; 0 ambiguous matches dropped. - 1,362 API requests, 0 unrecoverable failures. The /search.json overview endpoint 500-errors for 7 member IDs on whole-history queries; their 'member' gag counts were computed by summing 4-year windows instead. - The API's SpokenResultCount field is broken (always 0) — pagination-based counting used throughout, hence exact. - 'anti-climax' matches the word-boundary regex for climax; both such hits were classified false positive by hand. - Burnham's only near-hits are 'escort' (airport security / police-escort jibe at Andrew Lansley) and 'stimulation' (spinal cord, pain treatment) — all false positives. The Prime Minister scores zero. - Zero hits in all of Hansard for any cabinet member: viagra variants aside from Bryant's, orgasm, threesome, libido, aphrodisiac, foreplay, nipple, g-spot, sex toy, onlyfans, blue balls, gigolo, dominatrix, chastity, dogging, bondage (sexual sense), missionary (sexual sense), frenulum, rectum. Parliament is less fun than hoped. --- # Addendum: the all-time analysis (all speakers, 1803–2026) ## Approach Instead of per-member queries (~50,000 requests for all MPs in history), the all-time analysis inverts the search: **one date-partitioned sweep per term variant** across the entire Hansard record. Total cost: **426 API requests** (reconnaissance: ~70 count queries first, so volumes were known before any bulk fetching). 36,941 unique (contribution, term) rows, stored in SQLite (`alltime/hansard_all.db`, 567 MB with full texts, kept server-side). ## Speaker and party resolution (tiered) 1. **2005– (attributed era):** Hansard MemberId → ParlParse `datadotparl_id` join (offline). 82 IDs missing from ParlParse resolved via the Members API (alltime/mnis_fallback.py, cached). 2. **Pre-2005:** the `AttributedTo` string is parsed (office wrappers, titles, initials, compound surnames, optional constituency) and matched against mySociety's ParlParse dataset (14,792 persons, memberships back to 1761 including Historic Hansard data), validated against service dates, constituency as the strongest disambiguator. 3. **Unresolvable strings** (chiefly pre-1999 Lords, whom ParlParse does not cover, surname-only follow-ups like "Mr. Mellor", and office-only lines like "THE LORD CHANCELLOR") aggregate as name-buckets, flagged in the `resolution` column; office buckets and unattributed rows are excluded from rankings. 53.3% of rows resolve to a specific person; resolution is much higher in the modern era, where most genuinely sexual usage lives. 4. **Party:** ParlParse party-at-date where recorded (~1980s onward), then backfilled from **Wikidata P102** via the TheyWorkForYou-ID property (P2171) — 2,438 additional people, in ~25 bulk SPARQL queries. Party is known for 43% of counted mentions; the party table shows only rows with known party, and per-speaker-year rates are computed only where ParlParse records party service years (roughly the modern era). Historic parties (Liberal, Whig, Irish Parliamentary) appear with totals but no rate. ## Counting: why the all-time headline is "strict" The same regex verification and false-positive rules as the cabinet analysis were applied to all 36,941 rows (plus the cabinet run's 11 hand adjudications, re-applied by contribution ID). At cabinet scale every machine-flagged "review" row was checked by hand; at 11,652 review rows that is impossible, so the all-time outputs report three counts per speaker: - **strict** (headline): rule-classified *relevant* only — unambiguously sexual-sense usage. Robert Peel's 125 "intercourse between the two countries" mentions score zero here, as they should. - **cleaned incl. review**: raw minus classified false positives — the same definition as the cabinet run, but with review rows unaudited. - **raw**: everything the search matched. All-time totals: strict 11,263 · cleaned 28,665 · raw 51,067. ## Validation Cabinet members' all-time strict counts reproduce the cabinet pipeline's hand-audited cleaned counts (Alan Campbell: 46 = 26 prostitute + 20 lap dance in both). The top of the all-time table is historically coherent: Lord Stonham (Home Office minister, 1960s Sexual/Street Offences Bills), Lord Brett and Lord Falconer (Lords ministers on the 2009 Policing and Crime Bill and 2003 Sexual Offences Bill), W. R. Rees-Davies (1970s prostitution law), Lynda Waltho and Roberta Blackman-Woods (the 2008–09 lap-dancing licensing campaign). ## All-time caveats 1. Ministers and whips who pilot sex-industry legislation dominate — the brief-inflation caveat applies even more strongly across history. 2. Pre-1999 Lords cannot be resolved to persons or parties; several appear as name-buckets (e.g. LORD STONHAM) with no service years, so they appear in the total ranking but not the per-year ranking. 3. Hereditary peerage titles recur across generations (Lord Avebury 1900 is not Lord Avebury 1971); Lords memberships with unknown start dates are only trusted from 1999, so earlier same-title rows stay as honest name-buckets rather than being attached to the modern holder. 4. 19th-century speakers sharing names (three Sir Robert Peels) may blend within a name match; this materially affects no one in the strict top 50. 5. Historic Hansard's coverage and editorial conventions differ from the modern record; pre-1909 Hansard is not verbatim, so historic counts are floors. 6. Sources: Hansard API (Open Parliament Licence v3.0), mySociety ParlParse (people.json), Wikidata (CC0). Total external requests for the entire all-time analysis: ~600.