Decatur Townhouses prices gathered from the Dekalb County Tax Commissioner website. I've excluded gifts or inherited "sales" and some other outliers. There are obviously sales from before 1982, but at least online they don't give the actual values for those. Their records only go through 2017 right now. 2018 sales will be updated in 2019.
xxxxxxxxxx
<style>
body {
font: 10px sans-serif;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js">
</script>
<script>
const numberWithCommas = (x) => {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d){
return "<strong>Price: </strong>$" + numberWithCommas(d.close) + "</span><br/>Date: " + d.date.toDateString().substring(4) + "<br/>Unit: " + d.unit_letter + d.unit_number + "<br/>Deed Type: " + d.deed_type + "<br/>Sale Condition: " + d.sale_condition;
});
var svg = d3.select("svg"),
margin = {top: 70, right: 20, bottom: 30, left: 80},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.call(tip);
var parseTime = d3.timeParse("%m/%d/%Y");
var dotSize = 2.5;
var selectedDotSize = 3.5;
var x = d3.scaleTime()
.rangeRound([0, width]);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
d3.tsv("data.tsv", function(d) {
d.date = parseTime(d.date);
d.close = +d.close;
return d;
}, function(error, data) {
if (error) throw error;
data = data.sort(function(a, b) {return new Date(a.date)-new Date(b.date);});
two_bedroom_data = data.filter(
function(d) {
if (+d.bedrooms == 2) {
return d;
}
}
);
three_bedroom_data = data.filter(
function(d) {
if (+d.bedrooms == 3) {
return d;
}
}
);
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, 350000]);
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.select(".domain")
.remove();
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Price ($)");
g.append("path")
.datum(two_bedroom_data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
g.selectAll(".dot").data(two_bedroom_data).enter().append("circle")
.attr("r", dotSize)
.style("fill", "steelblue")
.attr("cx", function(d) {return x(d.date);})
.attr("cy", function(d) {return y(d.close);})
.on('mouseover', function(d){
d3.select(this).style("r", selectedDotSize).style("fill", "black");
tip.show(d,this);
})
.on("mouseout", function(d){
d3.select(this).style("r", dotSize).style("fill", "steelblue");
tip.hide(d, this);
});
g.append("path")
.datum(three_bedroom_data)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-width", 1.5)
.attr("d", line);
g.selectAll(".dot").data(three_bedroom_data).enter().append("circle")
.attr("r", dotSize).style("fill", "red")
.attr("cx", function(d) {return x(d.date);})
.attr("cy", function(d) {return y(d.close);})
.on('mouseover', function(d){
d3.select(this).style("r", selectedDotSize).style("fill", "black");
tip.show(d,this);
})
.on("mouseout", function(d){
d3.select(this).style("r", dotSize).style("fill", "red");
tip.hide(d, this);
});
});
</script>
https://d3js.org/d3.v4.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js