Skip to content

Instantly share code, notes, and snippets.

@captainelaine
Created February 27, 2016 20:07
Show Gist options
  • Save captainelaine/a2afb7a3964e7640e7bc to your computer and use it in GitHub Desktop.
Save captainelaine/a2afb7a3964e7640e7bc to your computer and use it in GitHub Desktop.
Dots on Lines
Driver 2007 2008 2009 2010 2011 2012 2013 2014 2015
Lewis Hamilton 109 98 49 240 227 190 189 384 381
Nico Rosberg 20 17 34.5 142 89 93 171 317 322
Sebastian Vettel 6 35 84 256 392 281 397 167 278
Kimi Raikkonen 110 75 48 207 183 55 150
Felipe Massa 94 97 22 144 118 122 112 134 121
Nico Hulkenberg 22 63 51 96 58
Romain Grosjean 0 96 132 8 51
Jenson Button 6 3 95 214 270 188 73 126 16
Fernando Alonso 109 61 26 252 257 278 242 161 11
Mark Webber 10 21 69.5 242 258 179 199
Adrian Sutil 1 0 5 47 42 29
Heikki Kovalainen 30 53 22 0 0 0 0
Robert Kubica 39 75 17 136
Rubens Barrichello 0 11 77 47 4
Jarno Trulli 8 31 32.5 0 0
Nick Heidfeld 61 60 19 6 34
<link href='https://fonts.googleapis.com/css?family=Ubuntu:300italic,500|Josefin+Sans:400italic' rel='stylesheet' type='text/css'>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>F1 drivers' performances from 2007-2015</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<style type="text/css">
body {
background-color: white;
font-family: 'Ubuntu', sans-serif;
text-align: center;
line-height: 20px;
}
h1 {
font-size: 24px;
margin: 0;
}
p {
font-size: 14px;
margin: 10px 0 0 0;
}
svg {
background-color: white;
opacity: 0.9;
}
.axis path,
.axis line {
fill: none;
stroke: white;
shape-rendering: crispEdges;
stroke-width: 0px;
}
.line.unfocused{
stroke-opacity: 40%;
}
.line.focused {
stroke-width: 3px;
stroke-opacity: 100%;
}
.line {
stroke: grey;
fill: none;
stroke-opacity: 50%;
stroke-width: 2px;
}
#focused {
stroke-width: 2px;
stroke-opacity: 100px;
opacity: 1;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
.tooltip {
position: absolute;
z-index: 10;
}
.tooltip p {
background-color:white;
border: none;
padding: 2px;
font-style: italic;
}
.name-label {
font-size: 15px;
font-style: italic;
font-family: 'Josefin Sans', sans-serif;
opacity: 0.5;
}
.name-label.focused {
opacity: 1;
width: 3px;
}
#high {
color: rgb(154,31,36);
}
a:hover{
color: red;
}
text.hidden {
display: none;
}
text.bolder {
font-weight: bolder;
}
</style>
</head>
<body>
<h1>F1 drivers' performances from Season 2007 - Season 2015</h1>
<p>In the field of Formula One, it is very normal that some drivers will quit the championship due to bad performance or other reasons.</br>It is also pretty natual that drivers will change their teams every season.</p>
<p id = "high">However,as the performances of drivers in the race depends a lot on the competitiveness of their race cars. </br>Although a driver's car skill is good enough, there is still little chance that he can win a race with a slow car.</p>
<p>Thus in this chart, you may see some drivers always remain their points achieved during the season in a high level. </br>Otherwise, some drivers, for example, Fernando Alonso, whose performance floated a lot during the last couple years due to his transfer to other car teams.</p>
<p id="sources"><em><a href= "https://en.wikipedia.org/wiki/Formula_One">Source</a></em></p>
<script type="text/javascript">
var fullwidth = 1130;
var fullheight = 530;
var margin = {top:50, right: 150, bottom: 50, left:100};
var width = fullwidth - margin.left - margin.right;
var height = fullheight - margin.top - margin.bottom;
var dateFormat = d3.time.format("%Y");
var xScale = d3.time.scale()
.range([0,width]);
var yScale = d3.scale.linear()
.range([0, height]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10)
.tickFormat(function(d){
return dateFormat(d);
})
.innerTickSize([10])
.outerTickSize([10]);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.outerTickSize([10])
;
var line = d3.svg.line()
.x(function(d) {
return xScale(dateFormat.parse(d.year));
})
.y(function(d) {
return yScale(+d.amount);
});
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip");
var svg = d3.select("body")
.append("svg")
.attr("width",fullwidth)
.attr("height", fullheight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("f1driverpoint_timeline.csv",function(data){
var years = ["2007","2008","2009","2010","2011","2012","2013","2014","2015"];
var dataset= [];
data.forEach(function(d,i){
var points = [];
years.forEach(function (y){
if (d[y]) {
points.push({
year: y,
amount: d[y]
});
}
});
dataset.push({
driver: d.Driver,
point: points
});
});
console.log(dataset);
xScale.domain(
d3.extent(years, function(d){
return dateFormat.parse(d);
})
);
yScale.domain([
d3.max(dataset, function(d){
return d3.max(d.point, function(d) {
return +d.amount;
});
}),
0
]);
var groups = svg.selectAll("g.lines")
.data(dataset)
.enter()
.append("g")
.attr("class", "lines")
.on("mouseover", mouseoverFunc) // putting these on the g nodes gets us a lot!
.on("mouseout", mouseoutFunc);
groups.append("title")
.text(function(d){
return d.driver;
});
groups.selectAll("path")
.data(function(d){
return [d.point];
})
.enter()
.append("path")
.attr("class","line")
.attr("d", line)
.style("stroke", function(d){
return color(d);
});
groups.sort(function(a,b){
return d3.ascending(+a.Driver,+b.Driver);
})
.transition()
.delay(function(d,i){
return i*10;
})
.duration(1000)
.attr("d",line);
var circles = groups.selectAll("circle")
.data(function(d){
return d.point;
})
.enter()
.append("circle");
circles.attr("cx",function(d){
return xScale(dateFormat.parse(d.year));
})
.attr("cy",function(d){
return yScale(+d.amount);
})
.attr("r",3)
.style("opacity",0);
circles
.on("mouseover", mouseoverCircle)
.on("mousemove",mousemoveCircle)
.on("mouseout", mouseoutCircle);
groups.append("text")
.datum(function(d){
return{
name: d.driver,
value: d.point[d.point.length - 1]
};
})
.attr("transform", function(d){
return "translate("+ (width + 3) + "," + yScale(+d.value.amount) +")";
})
.attr("x",3)
.attr("dy", "1px")
.text(function(d){
return d.name;
})
.classed("name-label",true);
d3.selectAll(".name-label")
.classed("hidden",function(d,i){
if(i<=4|| i===9 ||i===8 ||i ===5) {
return false;
} else {
return true;
}
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
d3.selectAll("g.lines")
.on("mouseover", mouseoverFunc)
.on("mouseout", mouseoutFunc);
// this version calls a named function.
svg.append("text")
.attr("class", "xlabel")
.attr("transform", "translate(" + (margin.left + width / 2) + " ," +
(height + margin.bottom) + ")")
.style("text-anchor", "middle")
.attr("dy", "-1px")
.attr("dx", "-70px")
.text("Season");
svg.append("text")
.attr ("class", "ylabel")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left) // you may need to adjust this
.attr("x", 0 - (height / 2)) // you may need to adjust
.attr("dy", "3em")
.style("text-anchor", "middle")
.text("Total Points");
function mouseoverFunc(d) {
// line styling:
// this is the g element. select it, then the line inside it!
//console.log(d, this);
d3.selectAll("path.line").classed("unfocused", true);
// now undo the unfocus on the current line and set to focused.
d3.select(this).select("path.line").classed("unfocused", false).classed("focused", true);
d3.selectAll(".name-label").classed("unfocused", true);
// now undo the unfocus on the current line and set to focused.
d3.select(this).select(".name-label").classed("hidden", false).classed("focused", true);
}
function mouseoutFunc(d) {
// this removes special classes for focusing from all lines. Back to default.
d3.selectAll("path.line").classed("unfocused", false).classed("focused", false);
tooltip.style("display", "none");
d3.selectAll(".name-label").classed("focused",false).classed("hidden", true).classed ("hidden", function(d,i){
if (i<=4|| i===9 ||i===8 ||i ===5) {
return false;
}else {
return true;
}
})
// now undo the unfocus on the current line and set to focu // this sets it to invisible!
}
function mouseoverCircle(d) {
d3.select(this)
.transition()
.style("opacity",1)
.style("fill", "grey")
.attr("r", 6);
tooltip
.style("display", null)
.html("<p>Season:" +d.year +
"<br>Points:" +d.amount + "</p>");
}
function mousemoveCircle(d) {
//console.log("events", window.event, d3.event);
tooltip
.style("top", (d3.event.pageY - 10) + "px" )
.style("left", (d3.event.pageX + 10) + "px");
}
function mouseoutCircle(d) {
d3.select(this)
.transition()
.style("opacity", 0)
.attr("r",3);
tooltip
.style("display","none");
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment