index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Federal Income Tax Rates</title>
<link rel="stylesheet" href="fedTaxes.css">
</head>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="fedTaxes.js"></script>
</body>
</html>
cleaningFedData.py
'''cleaning data for Feds
to execute, in correct directory type "python3 cleaningFedData.py"
- for when I'm ready to do other categories
myarray.append([year, row[5], row[6], row[4], 'married filed seperately', 'nominal'])
myarray.append([year, row[9], row[10], row[8], 'single', 'nominal'])
myarray.append([year, row[13], row[14], row[12], 'head of household', 'nominal'])
'''
import csv
def readList(filename):
''' reads in a file line by line
for each line it strips the new line character, turns it into an integer, and appends it to an array
'''
line_number = 0
myarray = [['tax_year', 'income_floor', 'income_ceiling', 'marginal_tax_rate', 'category', 'value']]
year = 0
with open(filename, encoding='utf-8') as a_file:
for a_line in a_file:
line_number += 1
row = a_line.rstrip().split(',')
if (row[2] == 'Nominal'):
year = row[6]
elif (row[0].split('.')[0] == '0'):
myarray.append([year, row[1], row[2], row[0], 'married filed jointly', 'nominal'])
return myarray
if __name__ == '__main__':
mylist = readList('FedDataToClean.csv')
with open('parseddata.csv', 'w', newline='') as fp:
a = csv.writer(fp, delimiter=',')
a.writerows(mylist)
fedTaxes.css
.focus text {
font-family: Times New Roman;
font-size: 24;
fill: orange;
}
div.tooltip {
position: absolute;
text-align: center;
width: 170px;
height: 14px;
padding: 2px;
font: 12px sans-serif;
background: white;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
fedTaxes.js
var barHeight = 5;
var income_factor = 2000;
var boxsize = 1000
var colorLow = '#ffffe5';
var colorHigh = '#004529';
var svgHolder = d3.select("body")
.append("svg")
.attr("width", boxsize)
.attr("height", boxsize);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 1e-6);
function setColorScale(max) {
return d3.scale.linear()
.domain([0, max])
.interpolate(d3.interpolateRgb)
.range([colorLow, colorHigh])
}
function drawRectangles(svg, mydata) {
var maxTax = 0;
var maxIncome = 0;
mydata.forEach(function(d) {
if (+d.marginal_tax_rate > maxTax) {
maxTax = +d.marginal_tax_rate;
};
if (+d.income_floor > maxIncome) {
maxIncome = +d.income_floor;
};
if (+d.income_floor == 0) {
d.income_floor = 1;
}
})
mydata.forEach(function(d) {
if (d.income_ceiling == 'na') {
d.income_ceiling = maxIncome;
};
})
colorScale = setColorScale(maxTax);
incomeScale = d3.scale.pow().exponent(.2).domain([1, maxIncome]).range([0, boxsize]);
console.log(maxIncome)
yearScale = d3.scale.linear().domain([1862, 2013]).range([500, 10]);
svg.selectAll("rect")
.data(mydata)
.enter()
.append("rect")
.attr("x", function(d, i) {
return incomeScale(+d.income_floor);
})
.attr("y", function(d, i) {
return yearScale(+d.tax_year)
})
.attr("width", function(d) {
return incomeScale(+d.income_ceiling) - incomeScale(+d.income_floor)
})
.attr("height", barHeight)
.attr("stroke", 'white')
.attr("fill", function(d) {
return colorScale(+d.marginal_tax_rate);
})
.on("mouseover", function() {
div.transition()
.duration(500)
.style("opacity", 1);
})
.on("mouseout", function() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
})
.on("mousemove", function(d) {
console.log(this);
var coord = d3.mouse(this);
var income = incomeScale.invert(coord[0]);
div
.text('year: '
+ Math.ceil(yearScale.invert(coord[1]))
+ ', income: '
+ d3.formatPrefix(income).scale(income).toFixed()
+ d3.formatPrefix(income).symbol)
.style("left", (coord[0] + 20) + "px")
.style("top", coord[1] + "px");
})
var prefix = d3.formatPrefix(13759402);
console.log(prefix.symbol);
console.log(prefix.scale(13759402).toFixed());
}
d3.csv("fed_income_tax.csv", function(error, dataset) {
drawRectangles(svgHolder, dataset);
});