Interactive graphic by Christopher Ingraham. Data from Voteview.com. Original concept by Brian Resnick, Brian McGill and Ella Krivitchenko of the National Journal.
The National Journal graphic offered a unique way of looking at party unity scores for the 113th Congress: Party unity % on a y-axis, and a straightforward rank within each party along a split x-axis. The graphic showed that only 20 Republicans and 39 Democrats had party unity scores less than 90%, indicating a high degree of partisanship and polarization.
So what did previous Congresses look like? Voteview.com provides party unity scores going back to the first Congress. I limited myself to the 35th, since prior to that large numbers of non-Democratic or Republican party members (Whigs, etc.) make comparisons less useful. I did have to omit records of approximately 300 non-Democratic or Republican members from my subset, representing about 1% of the 30,000 or so records examined.
In general, more-unified Congresses have a narrower "stem" and flatter "flare" at the top of the graph, while less-unified Congresses have a wider stem. I'd caution against reading too much into the general shapes, however, since these are partially influenced by the number of representatives in each party in any given session. The data do suggest that our era is relatively unique in the level of party unity within Congress. The only other time period posting similar unity scores is the turn of the 20th century. Other eras are notable for lopsided unity rates. Immediately following the civil war, Democrats showed a much more unified front than their Republican colleagues.
forked from cingraham's block: Party Unity in Congress, 1857 to 2011
xxxxxxxxxx
<meta charset="utf-8">
<html>
<head>
<title>House party unity</title>
<link rel = "stylesheet" type = "text/css" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
<link rel = "stylesheet" type = "text/css" href="slider.css">
<style type = "text/css">
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: relative;
}
#container {
padding: 10px;
width: 960px;
}
svg { background:rgb(255,255,255);position:relative;}
svg:not(:root) { overflow: hidden; }
.y.axis line {
stroke: #ccc;
stroke-dasharray: 1,3;
}
.x.axis line {
stroke: #666;
stroke-dasharray: 3,1;
}
.y.axis path {
display: none;
}
.y.axis .zero line {
stroke: #333;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.y.axis line {
stroke-dasharray: 5,5;
}
#tt { pointer-events: none;color:white;}
#tipContainer { font-size:16px;position:absolute;width:180px;z-index:100;background-repeat:no-repeat;text-align:left;line-height:20px;}
#tipLocation {font-weight:normal;font-family:Georgia; font-style: Italic; color:white;margin:0px;padding:10px 10px;background:#333;font-size:14px;}
#tipCount {font-weight:bold;font-size:32px;letter-spacing:-1px;margin:0px;padding:0px 10px 10px 10px;color:#333;}
#tipKey {font-weight:normal;font-size:24px;font-weight: bold; color:#333;margin:0px;padding:5px 0px 5px 10px;background:#eee;}
.tipClear { clear:both;}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js" type="text/javascript"></script>
<script src="bootstrap-slider.js"></script>
</head>
<body>
<h3 style = "font-size: 18px;"><i>Party unity scores among Democrat and Republican House members, 1857 - 2011</i></h3>
<p><b>Use the slider to select a Congress:</b></p>
<div style = "padding: 10px;">
<input type="text" class="slider" value="" data-slider-min="35" data-slider-max="112" data-slider-step="1" data-slider-value="-14" data-slider-orientation="horizontal" data-slider-selection="after">
</div>
<div id = "container">
</div>
<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 10, right: 20, bottom: 20, left: 40},
w = 800 - margin.left - margin.right,
h = 500 - margin.top - margin.bottom;
var formatpct = d3.format(".1%");
var x = d3.scale.linear()
.range([0, w])
.domain([-350, 350]);
var y = d3.scale.linear()
.range([h, 0])
.domain([0, 100]);
var red = "#bb1813", blue = "#0071bc";
var sl = $('.slider').slider();
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(5)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.tickSize(-w)
.orient("left");
var svg = d3.select("#container").append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tooltip = d3.select("#container")
.append("div")
.attr("id", "tt")
.style("z-index", "10")
.style("position", "absolute")
.style("visibility", "hidden");
d3.csv("hfinal.csv", function(error, data) {
data.forEach(function(d) {
d.pct = + d.pct;
d.congress = +d.congress;
});
var subset = data.filter(function(d) { return d.congress == 35; });
var subrep = subset.filter(function(d) { return d.party == 200; });
subrep = subrep.sort(function(a,b) { return a.pct - b.pct;});
var subdem = subset.filter(function(d) { return d.party == 100; });
subdem = subdem.sort(function(a,b) { return a.pct - b.pct;});
var dem90 = subdem.filter(function(d) { return d.pct > 90 });
var dem90num = dem90.length;
var dem90pct = formatpct(dem90num / subdem.length);
var rep90 = subrep.filter(function(d) { return d.pct > 90 });
var rep90num = rep90.length;
var rep90pct = formatpct(rep90num / subrep.length);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "ylabel")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Percentage of votes with respective party");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.append("text")
.attr("class", "xlabel")
.attr("x", w)
.attr("y", -6)
.style("text-anchor", "end")
.text("Party unity ranking (negative values for Democrats, positive for Republicans)");
svg.selectAll(".reddot")
.data(subrep)
.enter().append("circle")
.attr("class", "reddot")
.attr("r", 6)
.attr("cx", function(d, i) {return x(i); })
.attr("cy", function(d) {return y(d.pct); })
.style("fill", red)
.style("fill-opacity", 0.2)
.on("mouseover", function(d) {return toolOver(d, this) })
.on("mouseout", function(d) { return toolOut(d, this) })
.on("mousemove", function(d, i) {
myPos = d3.mouse(this);
myX = myPos[0];
myY = myPos[1];
return toolMove(d.rep, d.pct)});
svg.selectAll(".bluedot")
.data(subdem)
.enter().append("circle")
.attr("class", "bluedot")
.attr("r", 6)
.attr("cx", function(d, i) {return x(-i); })
.attr("cy", function(d) {return y(d.pct); })
.style("fill", blue)
.style("fill-opacity", 0.2)
.on("mouseover", function(d) {return toolOver(d, this) })
.on("mouseout", function(d) { return toolOut(d, this) })
.on("mousemove", function(d, i) {
myPos = d3.mouse(this);
myX = myPos[0];
myY = myPos[1];
return toolMove(d.rep, d.pct)});
//.attr("stroke", "#fff");
var val = sl.data('slider').getValue();
svg.append("text")
.attr("id", "congnum")
.style({"font-size":"36px","font-weight":"bold", "fill":"#333", "text-anchor": "end"})
.attr("x", w - 10)
.attr("y", h - 195)
.text(ordinal_suffix_of(val) + " Congress");
svg.append("text")
.attr("id", "yearnum")
.style({"font-size":"36px","font-weight":"bold", "fill":"#333", "text-anchor": "end"})
.attr("x", w - 10)
.attr("y", h - 150)
.text("(" + getYear(val) + " to " + (getYear(val) + 2) +")");
svg.append("text")
.attr("id", "hed")
.style({"font-size":"14px","font-style":"italic", "fill":"#333", "text-anchor": "end"})
.attr("x", w - 10)
.attr("y", h - 120)
.text("Reps. with party unity scores greater than 90%:");
svg.append("text")
.attr("id", "demnum")
.style({"font-size":"18px","font-weight":"bold", "fill":blue, "text-anchor": "end"})
.attr("x", w - 10)
.attr("y", h - 90)
.text(dem90num + " Democrats (" + dem90pct + ")");
svg.append("text")
.attr("id", "repnum")
.style({"font-size":"18px","font-weight":"bold", "fill":red, "text-anchor": "end"})
.attr("x", w - 10)
.attr("y", h - 65)
.text(rep90num + " Republicans (" + rep90pct + ")");
sl.on('slide', function() {update(data)});
});
function update(data) {
var congress = sl.data('slider').getValue();
//$('#sliderDivId').data('slider').getValue()
svg.selectAll("#congnum")
.text(ordinal_suffix_of(congress) + " Congress");
svg.selectAll("#yearnum")
.text("(" + getYear(congress) + " to " + (getYear(congress) + 2) +")");
var subset = data.filter(function(d) { return d.congress == congress; });
var subrep = subset.filter(function(d) { return d.party == 200; });
subrep = subrep.sort(function(a,b) { return a.pct - b.pct;});
var subdem = subset.filter(function(d) { return d.party == 100; });
subdem = subdem.sort(function(a,b) { return a.pct - b.pct;});
var dem90 = subdem.filter(function(d) { return d.pct > 90 });
var dem90num = dem90.length;
var dem90pct = formatpct(dem90num / subdem.length);
var rep90 = subrep.filter(function(d) { return d.pct > 90 });
var rep90num = rep90.length;
var rep90pct = formatpct(rep90num / subrep.length);
svg.selectAll("#demnum")
.text(dem90num + " Democrats (" + dem90pct + ")");
svg.selectAll("#repnum")
.text(rep90num + " Republicans (" + rep90pct + ")");
var redcirc = svg.selectAll(".reddot")
.data(subrep);
redcirc.enter().append("circle")
.attr("cx", x(0))
.attr("r", 6)
.transition()
.attr("cx", function(d, i) {return x(i); })
redcirc.exit().remove();
redcirc
.attr("class", "reddot")
.attr("cx", function(d, i) {return x(i); })
.attr("cy", function(d) {return y(d.pct); })
.style("fill", red)
.style("fill-opacity", 0.2)
.on("mouseover", function(d) {return toolOver(d, this) })
.on("mouseout", function(d) { return toolOut(d, this) })
.on("mousemove", function(d, i) {
myPos = d3.mouse(this);
myX = myPos[0];
myY = myPos[1];
return toolMove(d.rep, d.pct)});
var bluecirc = svg.selectAll(".bluedot")
.data(subdem);
bluecirc.enter().append("circle")
.attr("r", 6);
bluecirc.exit().remove();
bluecirc
.attr("class", "bluedot")
.attr("cx", function(d, i) {return x(-i); })
.attr("cy", function(d) {return y(d.pct); })
.style("fill", blue)
.style("fill-opacity", 0.2)
.on("mouseover", function(d) {return toolOver(d, this) })
.on("mouseout", function(d) { return toolOut(d, this) })
.on("mousemove", function(d, i) {
myPos = d3.mouse(this);
myX = myPos[0];
myY = myPos[1];
return toolMove(d.rep, d.pct)});
}
function ordinal_suffix_of(i) {
var j = i % 10;
if(i == 111 || i == 112) {
return i + "th";
}
if (j == 1 && i != 11) {
return i + "st";
}
if (j == 2 && i != 12) {
return i + "nd";
}
if (j == 3 && i != 13) {
return i + "rd";
}
return i + "th";
}
function getYear(number) {
return 1822 + number + (number - 35);
}
function toolOver(v, thepath) {
d3.select(thepath).style({"stroke":"#000"});
return tooltip.style("visibility", "visible");
};
function toolOut(m, thepath) {
d3.select(thepath).style({"stroke":"none"});
return tooltip.style("visibility", "hidden");
};
function toolMove(b, nb) {
return tooltip
.style("top", myY+60+"px")
.style("left", myX-140+"px")
.html("<div id='tipContainer'><div id='tipLocation'><b>"+b+ "</b></div><div id='tipKey'>"+formatpct(nb/100)+"</div><div class='tipClear'></div> </div>");
};
d3.select(self.frameElement).style("height", "700px");
</script>
</body>
</html>
Modified http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js to a secure url
Modified http://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js to a secure url
Modified http://d3js.org/d3.v3.min.js to a secure url
https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
https://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js
https://d3js.org/d3.v3.min.js