Skip to content

Instantly share code, notes, and snippets.

@pinsterdev
Last active June 19, 2020 12:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pinsterdev/234b4a5310a14a32e080 to your computer and use it in GitHub Desktop.
Save pinsterdev/234b4a5310a14a32e080 to your computer and use it in GitHub Desktop.
Daft Rental costs

Daft.ie rental prices and volumes.

Dublin rentals only, advertised "per month". Select statistic. Float over markers for more info. Raw data here. (v0.8)

<html>
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<br><br>
<div id="chart" style="float: left;"></div>
<div style="float: left; margin: 250px 0px 0px 40px;">
<div>
<strong>Statistic</strong>
<form name="selS" action="">
<input type="radio" id="radio11" name="selS" onclick="selStat(0)" checked>Median monthly rent<br>
<input type="radio" id="radio12" name="selS" onclick="selStat(1)">Average monthly rent<br>
<input type="radio" id="radio13" name="selS" onclick="selStat(2)">Volume available<br>
</form>
</div>
<div><br><h1><span id="lastupdate" style="line-height: 0px;"></span>
</h1><p><span style="line-height: 0px;"><small>(LAST UPDATE)</small></span></div>
</div>
<br>
<div style="clear: both"></div>
<div id="readme"></div>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script src="//cdn.rawgit.com/showdownjs/showdown/1.3.0/dist/showdown.min.js"></script>
<script src="/pinsterdev/raw/a2fcc47fae884342e190/util.js"></script>
<script src="https://api.github.com/gists/0f82dc8380acfd77299724369184a01d?callback=gistDataLoaded"></script>
<script src="main.js"></script>
</body>
</html>
body {
font: 12px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
line.axis2 {
display: none;
}
path.line {
fill: none;
stroke-width: 3;
}
.tick line{
stroke: lightgrey;
opacity: 0.4;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip .h {
font-weight: normal;
}
.d3-tip .vm {
font-weight: bold;
color: #ff8080;
}
.d3-tip .vp {
font-weight: bold;
color: lightgreen;
}
/* 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;
}
#readme {
width: 960px;
}
#chart {
width: 960px;
height: 500px;
}
readme(document.getElementById("readme"));
var chartElem = d3.select("body #chart");
var yAxisLabel = ["Median Monthly Rent (€)", "Average Monthly Rent (€)", "Number available"];
var currSym = ['€','€','',], fmt = d3.format(',f');
var statMetas = [
[ {n: "MedApt1", d: "1-bed Apt", c: "A"},
{n: "MedApt2", d: "2-bed Apt", c: "A"},
{n: "MedApt3", d: "3-bed Apt", c: "A"},
{n: "MedHse2", d: "2-bed Hse", c: "H"},
{n: "MedHse3", d: "3-bed Hse", c: "H"} ],
[ {n: "AvgApt1", d: "1-bed Apt", c: "A"},
{n: "AvgApt2", d: "2-bed Apt", c: "A"},
{n: "AvgApt3", d: "3-bed Apt", c: "A"},
{n: "AvgHse2", d: "2-bed Hse", c: "H"},
{n: "AvgHse3", d: "3-bed Hse", c: "H"} ],
[ {n: "VolApt", d: "Aptment", c: "A"},
{n: "VolHse", d: "House", c: "H"},
{n: "VolTot", d: "Total", c: "H"} ]];
//Pop up tip when floating over marker
var dateFmt = d3.time.format("%d-%b-%Y");
var tip = d3.tip().attr('class', 'd3-tip').offset([ -10, 0 ]).html(
function(d) {
// Include value in tip
var s = "<span class='h'>" + dateFmt(d.date) + ":</span> <span class='v'>" +
currSym[selectedStat] + fmt(d.value) + "</span>";
return s;
});
var margin = {
top : 20,
right : 80,
bottom : 60,
left : 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(6).tickFormat(d3.time.format("%d-%b"))
.tickSize(-height, 0, 0);
var xAxis2 = d3.svg.axis().scale(x)
.orient("bottom").ticks(d3.time.years, 1)
.tickFormat(d3.time.format("%Y")).tickSize(5,0);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5)
.tickSize(-width, 0, 0);
var color = d3.scale.category10();
var sheet = extractGistData(gistData["DaftData.csv"].content);
var allStats = mungeData(sheet);
d3.select("#lastupdate").html(sheet.rowName.replace("X","").replace(/_/g, "-"));
var selectedStat = parseParamWithDefault('s',['median','average','volume']);
document.selS.selS[selectedStat].checked = true;
doSvg();
/**
* Selection changed - remove and redo graph
*/
function selStat(s) {
selectedStat = s;
d3.select("svg").remove();
doSvg();
}
function doSvg() {
var statMeta = statMetas[selectedStat];
var statNames = statMeta.map(function (d) {return d.n});
var data = allStats.filter(function (d) {return statNames.indexOf(d.name) > -1;});
var isApt = function(d) {return statMeta[statNames.indexOf(d)].c=="A";};
color.domain(statNames);
// Adds the svg canvas
var svg = chartElem.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(tip)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the data
x.domain([d3.min(data, function(d) { return d3.min(d.values, function(v){return v.date;})}),
d3.max(data, function(d) { return d3.max(d.values, function(v){return v.date;})})]);
y.domain([d3.min(data, function(d) { return d3.min(d.values, function(v){return v.value;})}),
d3.max(data, function(d) { return d3.max(d.values, function(v){return v.value;})})]);
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "1.8em")
.attr("dy", "1.15em")
.attr("transform", "rotate(-0)" );
svg.append("g")
.attr("class", "x axis2")
.attr("transform", "translate(0," + (height+25) + ")")
.call(xAxis2);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis).append("text")
.attr("transform", "rotate(-90)").attr("y", 6).attr("dy",
".71em").style("text-anchor", "end").text(yAxisLabel[selectedStat]);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
var series = svg.selectAll(".series").data(data).enter()
.append("g").attr("class", "series");
series.append("path")
.attr("class", "line")
.attr("d", function(d) { return valueline(d.values); })
.style({stroke: function(d) {return color(d.name);}});
series.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) {return "translate(" + x(d.value.date) + "," +
(y(d.value.value)+(isApt(d.name)? 12 : -12)) + ")"; })
.attr("x", 6)
.attr("dy", ".35em")
.style({fill: function(d) {return color(d.name);}})
.text(function(d) { return statMeta[statNames.indexOf(d.name)].d; });
series.append("g").selectAll('.marker')
.data(function (d){return d.values}).enter()
.append(function(v) {
var elem;
if (isApt(v.name)) {
elem = document.createElementNS("http://www.w3.org/2000/svg", "circle");
elem.setAttribute("r", 5);
} else {
elem = document.createElementNS("http://www.w3.org/2000/svg", "rect");
elem.setAttribute("width", 10);
elem.setAttribute("height", 10);
}
return elem;
})
.attr("class", "marker")
.style({fill: function(v) {return color(v.name);}})
.attr("transform", function(v) { return "translate(" + (x(v.date)+(isApt(v.name)?0:-5)) +
"," + (y(v.value)+(isApt(v.name)?0:-5)) + ")"; })
.on('mouseover', tip.show).on('mouseout', tip.hide);;
}
function mungeData(sheet) {
// Parse the date / time
var parseDate = d3.time.format("%Y%m%d").parse;
var values = sheet.colNames.map(function(name) {
return {
name : name,
values : sheet.data.map(function(d) {
return {
name : name,
date : parseDate(d[sheet.rowName]),
value : +d[name].replace(',','')
};
})
};
});
values.push(
{name: "VolTot", values: sheet.data.map(function(d) {
return {
name: "VolTot",
date : parseDate(d[sheet.rowName]),
value : (+d.VolHse.replace(',','')) + (+d.VolApt.replace(',',''))
};})});
return values;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment