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/best-practices/svd-labels-voting-patterns-...

5.3 KiB

title date category module problem_type component severity applies_when tags
SVD Labels Should Reflect Voting Patterns, Not Semantic Content 2026-04-04 docs/solutions/best-practices stemwijzer best_practice brief_system medium [Labeling SVD (Singular Value Decomposition) components in voting analysis Interpreting PCA/SVD dimensions in political party voting data Creating axis labels for voting compass or similar applications] [svd voting-analysis axis-labels dimensionality-reduction party-voting-patterns]

SVD Labels Should Reflect Voting Patterns, Not Semantic Content

Context

When labeling SVD components in the Stemwijzer explorer (explorer.py), initial labels were based on semantic analysis of motion titles — what topics motions appeared to discuss. However, SVD captures voting patterns, not semantic content.

This mismatch led to:

  • Labels that didn't match how parties actually voted
  • Right-wing parties appearing on the LEFT side of axes (violating the right-wing parties → right side constraint)
  • Confusion about what each component actually represents

Guidance

The Core Principle

SVD components represent voting unity patterns, not topic clusters.

When a motion appears on a component with a positive loading, it means parties that vote positively on that motion tend to vote similarly. The component captures this behavioral pattern, not the topic's semantic meaning.

Example: Component 1

Approach Label Why It's Wrong
Semantic "Sociale zekerheid vs economische liberalisering" Assumes defense + social care = welfare state
Voting "Rechts kabinetsbeleid vs links oppositiebeleid" Matches actual coalition vs opposition voting

Why Component 1 captures coalition-opposition:

  • 9 coalition + center parties vote one way
  • 6 opposition parties vote the other way
  • Motion topics can include defense (right votes for) AND social care (left votes for) because they're on opposite sides of the coalition-opposition divide

How to Label SVD Components

  1. Analyze actual voting patterns first

    • Query which parties vote positively vs negatively on each component
    • Look for coalition/opposition splits, cross-block alliances, or isolated parties
  2. Verify right-wing parties on RIGHT side

    • Check PVV, FVD, JA21, SGP positions
    • If they vote negatively while left parties vote positively, flip the axis
  3. Don't assume semantics match voting

    • A "defense" component may include social care motions if right-wing parties vote the same way on both
    • Cross-block alliances (e.g., PVV with SP on welfare) create components that don't fit left-right semantics
  4. Test with sample motions

    • Top positive-loading motions should align with positive-voting parties' priorities
    • Top negative-loading motions should align with negative-voting parties' priorities

Why This Matters

Without understanding that SVD captures voting patterns:

  • Labels will be misleading to users
  • Right-wing parties may appear on the wrong side of axes
  • Components may be mislabeled as "left" when they're actually "opposition"
  • Users get incorrect information about party positions

When to Apply

Apply this guidance when:

  • Creating or updating SVD/PCA component labels
  • Interpreting dimensionality reduction results in voting analysis
  • Building voting compasses or similar political guidance tools
  • Analyzing roll call votes or legislative voting data

Examples

Wrong Approach (Semantic)

# ❌ BAD: Based on motion topics, not voting patterns
SVD_THEMES = {
    1: {
        "label": "Sociale zekerheid vs economische liberalisering",
        # Reality: 9 coalition parties vote same way, 6 opposition vote opposite
    }
}

Correct Approach (Voting Patterns)

# ✅ GOOD: Based on actual voting behavior
SVD_THEMES = {
    1: {
        "label": "Rechts kabinetsbeleid vs links oppositiebeleid",
        "explanation": (
            "Deze as scheidt het kabinetsbeleid van de oppositie. "
            "9 coalitiepartijen stemmen aan de positieve kant, "
            "6 oppositiepartijen aan de negatieve kant."
        ),
    }
}

Verification Approach

To verify SVD component labels, check which parties have positive vs negative loadings on each component:

# From explorer.py - check party loadings for each component
for comp_num in range(1, 11):
    component_parties = svd_scores[svd_scores['component'] == comp_num]
    positive_parties = component_parties[component_parties['loading'] > 0]['party'].tolist()
    negative_parties = component_parties[component_parties['loading'] < 0]['party'].tolist()
    
    print(f"Component {comp_num}:")
    print(f"  Positive ({len(positive_parties)}): {positive_parties}")
    print(f"  Negative ({len(negative_parties)}): {negative_parties}")

Use this to verify:

  • Right-wing parties (PVV, FVD, JA21, SGP) appear on the correct side
  • The label matches the voting pattern, not just the topic