How many numbers do you need to describe a senator?
One hundred people decide everything that crosses the floor of the United States Senate. Each one casts hundreds of votes per Congress.
That's a lot of data. Let's see what's hiding inside it.
A story about PCA, told through 175 years of roll-call votes.
Scroll, or press →
One hundred people decide everything that crosses the floor of the United States Senate. Each one casts hundreds of votes per Congress.
That's a lot of data. Let's see what's hiding inside it.
Each row is a senator. Each column is a bill. Red for yea, blue for nay, white for absent.
It looks like static. There's structure in there — but you can't see it.
Pull out a single row. That's one senator's voting record — every yea, every nay, every absence — across all 679 roll calls of the Congress.
Each cell is a coordinate. Red is +1, blue is −1, white is 0. Stacked into a single vector, that row places this one senator at a single point in 679-dimensional space.
Every senator is one such point. PCA will look for the directions that best spread those 100 points apart.
Form the covariance matrix of the data. Find the directions of largest variance — its top eigenvectors.
Project the 679-dimensional points onto the first two of those directions. That's our new coordinate system: PC1 and PC2.
Each dot is one senator from the most recent Congress. We computed the projection without using any labels — no party, no state, no ideology. Just the raw votes.
Look what comes out.
PCA found them on its own. The leftmost dots are progressive Democrats — Markey, Sanders, Warren. The rightmost are conservative Republicans — Cornyn, Lankford, McConnell.
The first principal component has a name. Everyone agrees on it: liberal–conservative.
Watch the cloud morph. In the 1930s the parties overlap heavily — a New Deal coalition crossed party lines. In the 1960s the second principal component spikes: Southern Democrats voted with Republicans on civil rights but with Democrats on everything else.
By 2020 the two clouds have torn apart. There is almost no overlap.
Use the slider, or press ↑/↓.
Compare the scree plot of the 88th Congress (1963, civil rights era) with the 119th (today).
In 1963, the second eigenvalue is large — politics genuinely needed two dimensions. Today, the first eigenvalue swallows almost everything. Congress has become literally lower-dimensional.
We never told the algorithm what a party is. Two clusters, two random starting points, repeat until convergence.
It rediscovers the parties — with an Adjusted Rand Index of essentially 1.0 in the modern era.
k-means rediscovers the parties almost perfectly — in the 119th Senate, every Democrat ends up in one cluster and every Republican in the other. Nobody is misclassified.
But not every senator sits an equal distance from the dividing line. The boundary between the two clusters runs roughly down the middle. The dots nearest that line — coloured by their actual party, as before — are the senators who vote across party lines most often. Murkowski (R), Paul (R), Fetterman (D), Gallego (D): all on their party's side, but only just.
These are the senators journalists call swing votes. The algorithm has no idea who they are; it just sees that their voting record sits closer to the other cluster's centroid than any of their colleagues do.
Train a Random Forest to predict party from votes. Look at the feature importances.
The top votes aren't usually the famous, headline-grabbing ones. They're procedural: motions to table, cloture motions, motions to proceed. Procedural votes are nearly perfect party-line because they're about who controls the floor.
The first one has a name. The fact that the second one is shrinking is itself news.
Data: Voteview — Poole, Rosenthal, Lewis et al.