You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
motief/docs/solutions/insights/quantifying-political-extre...

4.9 KiB

title date module problem_type component tags
Quantifying Political Extremity: Voting vs Policy 2026-04-05 analysis research motion-analysis [polarization voting-extremity policy-extremity embedding-analysis parliamentary-motion]

Quantifying Political Extremity: Voting vs Policy

Context

Initial analysis of parliamentary motions sought to measure polarization by examining how "extreme" policies have become. The hypothesis was that extremes on both sides became more extreme. The analysis revealed this hypothesis was incorrect — and surfaced two independent phenomena.

Guidance

Key Finding: Two Independent Measures of Extremity

Voting Extremity and Policy Extremity are independent phenomena with different trends:

Measure 2016 2026 Trend
Voting Extremity (margin/total) 0.70 0.46 Parliament votes more closely
Policy Extremity (embedding distance from mainstream) 5.65 4.17 Policies are less extreme

Correlation: r ≈ 0 — these measures are statistically independent.

What Each Measures

Voting Extremity = abs(votes_for - votes_against) / total_votes

  • 1.0 = unanimous (all votes same direction)
  • 0.0 = perfectly split (50-50)
  • Captures how divided parliament is when voting

Policy Extremity = ||embedding - mainstream_centroid||

  • Euclidean distance in text embedding space (2560 dims)
  • Captures how far a motion is from the political center

How to Measure Each

# Voting Extremity
margin = abs(votes_for - votes_against)
total = votes_for + votes_against
voting_extremity = margin / total

# Policy Extremity (using text embeddings, not SVD)
from embeddings table (qwen/qwen3-embedding-4b)
policy_extremity = np.linalg.norm(motion_embedding - mainstream_centroid)

Why Use Text Embeddings (Not SVD)

SVD embeddings are fitted on voting patterns, capturing how parties vote together. They measure voting extremity, not policy extremity.

For policy content, use raw text embeddings (embeddings table, 2560 dimensions) which are computed from motion text only.

Bipartisan Anchor Approach

Define the "mainstream" as the centroid of bipartisan motions (80%+ parties vote the same way):

# Find bipartisan motions
bipartisan = [m for m in motions if majority_vote_pct >= 0.80]

# Compute mainstream centroid
mainstream_centroid = mean([m.embedding for m in bipartisan])

# Measure policy extremity
policy_extremity = ||motion.embedding - mainstream_centroid||

Why This Matters

The hypothesis "extremes became more extreme" was wrong because:

  1. Voting extremity increased — parliament votes more divided now
  2. Policy extremity decreased — even extreme motions are closer to center

This means: what divides parties changed, not how radical the policies are.

Quantifying Mainstream Shift

Using 2018 as baseline ("last normal year"):

Period Distance from 2018 Interpretation
2016-2018 ~0.22 Similar mainstream
2019 0.46 Shift begins
2020-2026 ~0.71 New stable mainstream

The mainstream shifted 0.71 units after 2018 and has remained stable.

Coalition Shift on Migration Policy

Parties that once opposed strict migration now vote for them:

Party 2016-2018 2025-2026 Change
VVD 100% voor 78% voor
CDA 100% voor 81% voor
D66 100% voor 60% voor ↓↓
PVV 20% voor 56% voor ↑↑
NSC 0% (new) 56% voor new
BBB 0% (new) 79% voor new

When to Apply

  • When analyzing parliamentary polarization trends
  • When comparing policy extremity across time periods
  • When studying coalition formation and party positioning
  • When testing hypotheses about political extremism

Examples

Correct Analysis

# Compare voting extremity and policy extremity separately
voting_ext = compute_voting_margin(motion)
policy_ext = compute_embedding_distance(motion, mainstream_centroid)

# Plot both trends independently
plot_trend(years, voting_ext, label="Voting Extremity")
plot_trend(years, policy_ext, label="Policy Extremity")

Incorrect Analysis

# DON'T use SVD scores to measure policy extremity
svd_score = motion.svd_vector[0]  # This measures voting pattern, not content!

# DO use text embeddings for policy content
text_embedding = embeddings_table[motion.id]
  • svd-stability-vs-overtone-shift.md — SVD axes measure voting structure, not semantics
  • policy-extremity-vs-voting-extremity.md — Initial documentation of the distinction

Visualizations

  • docs/research/polarization_comprehensive.png — Combined view of all metrics
  • docs/research/mainstream_shift.png — Mainstream shift over time
  • docs/research/voting_vs_policy_extremity.png — Independent trends