Created
March 15, 2016 02:13
-
-
Save claudialexa/e6b45285be80cdcb0d34 to your computer and use it in GitHub Desktop.
Changing Bars: The Sad Reality of My Fitbit Data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Date | Total | Calories Burned | Minutes Sedentary | Minutes Active | Activity Calories | |
---|---|---|---|---|---|---|
Monday 4 | 3468 | 1660 | 1378 | 62 | 367 | |
Tuesday 5 | 3131 | 1512 | 1398 | 42 | 178 | |
Wednesday 6 | 3480 | 1644 | 1317 | 123 | 394 | |
Thursday 7 | 4923 | 2290 | 1158 | 282 | 1185 | |
Friday 8 | 4900 | 2294 | 1193 | 247 | 1158 | |
Monday 11 | 3368 | 1614 | 1388 | 52 | 313 | |
Tuesday 12 | 3942 | 1882 | 1357 | 83 | 619 | |
Wednesday 13 | 3552 | 1669 | 1296 | 144 | 441 | |
Thursday 14 | 4261 | 2002 | 1247 | 193 | 816 | |
Friday 15 | 4822 | 2278 | 1236 | 204 | 1097 | |
Tuesday 19 | 4648 | 2184 | 1210 | 230 | 1020 | |
Wednesday 20 | 4582 | 2166 | 1228 | 212 | 970 | |
Thursday 21 | 3832 | 1786 | 1238 | 202 | 603 | |
Friday 22 | 4840 | 2270 | 1205 | 235 | 1123 | |
Monday 25 | 6644 | 3124 | 1080 | 360 | 2076 | |
Tuesday 26 | 10780 | 3200 | 887 | 308 | 1988 | |
Wednesday 27 | 3561 | 1674 | 1299 | 141 | 445 | |
Thursday 28 | 4289 | 1995 | 1204 | 236 | 850 | |
Friday 29 | 4314 | 2038 | 1030 | 298 | 943 | |
Saturday 30 | 3743 | 1767 | 1213 | 178 | 583 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Fitbit Data</title> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script> | |
<style> | |
body { | |
background: #ffffff; | |
color: #333; | |
margin: 1em auto 4em auto; | |
position: relative; | |
width: 960px; | |
font-family: sans-serif; | |
} | |
svg { | |
font: 10px sans-serif; | |
} | |
.bar rect { | |
fill: #00A388; | |
} | |
.bar rect:hover { | |
fill: #BEEB9F; | |
} | |
.value { | |
fill: white; | |
} | |
.axis { | |
shape-rendering: crispEdges; | |
} | |
.axis path { | |
fill: none; | |
stroke: none; | |
} | |
.x.axis path { | |
fill: none; | |
stroke: white; | |
} | |
.x.axis line { | |
stroke: #fff; | |
stroke-opacity: .8; | |
} | |
.y.axis path { | |
stroke: black; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-8"> | |
<h2>Fitbit Data: January Active Days</h2> | |
<p>By: Claudia Aguirre<br/> | |
Like every other person in the world, I set myself to start the year off by committing to going to the gym more. To understand the patterns of my gym attendance (and efficiency) I exported all of my Fitbit's January data (excluding the data of any days I may not have worn my Fitbit).</p> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-md-8"> | |
<p id="menu"><b>Activity Indicators: </b> | |
<select class="form-control"></select> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-md-8"><p id="chart"></p> | |
</div> | |
</div> | |
</div> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script> | |
var fullwidth = 800, | |
fullheight = 400; | |
var margin = {top: 30, right: 40, bottom: 10, left: 80}, | |
width = fullwidth - margin.right - margin.left; | |
height = fullheight - margin.top - margin.bottom; | |
var prevWorkout; | |
var xScale = d3.scale.linear() | |
.range([0, width]); | |
var yScale = d3.scale.ordinal() | |
.rangeRoundBands([0, height], .1); | |
var xAxis = d3.svg.axis() | |
.scale(xScale) | |
.orient("top") | |
.ticks(7); | |
var svg = d3.select("#chart").append("svg") | |
.attr("width", fullwidth) | |
.attr("height", fullheight) | |
.style("margin-left", -margin.left + "px") | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
svg.append("g") | |
.attr("class", "x axis"); | |
svg.append("g") | |
.attr("class", "y axis") | |
.append("line") | |
.attr("class", "domain") | |
.attr("y2", height); | |
var menu = d3.select("#menu select") | |
.on("change", redraw); | |
d3.csv("fitbit.csv", function(data) { | |
fitbit = data; | |
// remember d3.keys gets us the column names from these objects, using first row: | |
var workouts = d3.keys(fitbit[0]).filter(function(key) { | |
return key != "Date" && key != "Total"; | |
}); | |
console.log(workouts); | |
// build menu from the data; could have been done by hand. | |
menu.selectAll("option") | |
.data(workouts) | |
.enter().append("option") | |
.text(function(d) { return d; }); | |
menu.property("value", "Calories Burned"); | |
// redraw in this case draws the UI - it uses a variable to determine data column. | |
redraw(); | |
}); // end load csv | |
function redraw() { | |
// get the age for the data access off the menu: | |
var currentWorkout = menu.property("value"); | |
// sort by it and then take the top 10 using slice! | |
var top10 = fitbit.sort(function(a, b) { | |
return b[currentWorkout] - a[currentWorkout]; | |
}) | |
.slice(0, 15); | |
yScale.domain(top10.map(function(d) { return d.Date; })); // the y scale is ordinal, all the state names | |
var bar = svg.selectAll(".bar") | |
.data(top10, function(d) { return d.Date; }); // key function! | |
var barCreate = bar.enter().append("g") | |
.attr("class", "bar") | |
.attr("transform", function(d) { return "translate(0," + (yScale(d.Date) + height) + ")"; }) | |
.style("fill-opacity", 0); | |
console.log("date", prevWorkout); // this is undefined the first time thru. | |
barCreate.append("rect") | |
//.attr("width", age && function(d) { return x(d[age]); }) | |
.attr("width", function(d) { | |
if (prevWorkout) { | |
return xScale(d[prevWorkout]); | |
} | |
}) | |
.attr("height", yScale.rangeBand()); | |
barCreate.append("text") | |
.attr("class", "mylabel") | |
.attr("x", -3) | |
.attr("y", yScale.rangeBand() / 2) | |
.attr("dy", ".35em") | |
.attr("text-anchor", "end") | |
.text(function(d) { return d.Date; }); | |
barCreate.append("text") | |
.attr("class", "value") | |
//.attr("x", age && function(d) { return x(d[age]) - 3; }) | |
.attr("x", function(d) { | |
if (prevWorkout) { | |
return xScale(d[prevWorkout]) - 3; | |
} | |
}) | |
.attr("y", yScale.rangeBand() / 2) | |
.attr("dy", ".35em") | |
.attr("text-anchor", "end"); | |
prevWorkout = currentWorkout; | |
// they are sorted, so take the top value for the max on the domain here: | |
xScale.domain([0, top10[0][currentWorkout]]); | |
// sets the d.yLocation for the bar that's used in the exit transition. | |
var barUpdate = bar.transition() | |
.attr("transform", function(d) { | |
d.yLocation = yScale(d.Date); | |
return "translate(0," + yScale(d.Date) + ")"; }) | |
.style("fill-opacity", 1); | |
barUpdate.select("rect") | |
.attr("width", function(d) { return xScale(d[currentWorkout]); }); | |
barUpdate.select(".value") | |
.attr("x", function(d) { return xScale(d[currentWorkout]) - 3; }) | |
.text(function(d) { return (d[currentWorkout]); }); | |
var barExit = bar.exit().transition() | |
.attr("transform", function(d) { return "translate(0," + (d.yLocation + height) + ")"; }) | |
.style("fill-opacity", 0) | |
.remove(); | |
barExit.select("rect") | |
.attr("width", function(d) { return xScale(d[currentWorkout]); }); | |
barExit.select(".value") | |
.attr("x", function(d) { return xScale(d[currentWorkout]) - 3; }) | |
.text(function(d) { return (d[currentWorkout]); }); | |
// transition the axis, so easy if you fixed the domain! | |
svg.transition().select(".x.axis") | |
.call(xAxis); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment