Health trackers are the current craze. After I bought a Fitbit, I wanted to determine what exactly could I do with my Fitbit data. Can we learn something from this data that we did not know before? Most people don't need a watch to tell them that they walked a lot today or that they got a ton of sleep. We typically have a pretty good gauge of our basic physical health. I am interested in figuring out how we can use data science to look at our health over a longer period of time and learn something. Lets first look at a few things that people typically use Fitbit data for before we jump into the weeds. - Setting Goals - Motivation - Tracking Progress Ever since I bought a Fitbit, I found that I went to the gym a lot more frequently. Having something which keeps track of your progress is a great motivator. Not only is your daily steps recorded for your own viewing, you can share that data with your friends as a competition. Although I only have one friend on Fitbit, I found that was a good motivator to hit ten thousand steps every day. Goals which are not concrete never get accomplished. Simply saying that "I will get in shape" is a terrible goal. In order for you to actually accomplish your goals, they need to be quantifiable, reasonable, and measurable. Rather than saying "I will improve my health this year", you can say "I will loose ten pounds this year by increasing my daily step count to twelve thousand and go to the gym twice a week". One goal is wishy washy where the other is concrete and measurable. Having concrete data from Fitbit allows you to quantify your goals and set milestones for you to accomplish. Along the way to achieving your goal, you can easily track your progress. Simply knowing your Fitbit data can help you make more informed decisions about your fitness. You can tweak your life style after comparing your data against what is considered healthy. For example: if you notice that you are only getting 6 hours of sleep per night, you can look up the recommended amount of sleep and tweak your sleep routine until you hit that target. Alright, lets do some data science! ![Tom and Jerry Data Science Meme](media/fitbit/dataScience.jpg) # Getting The Data There are two options that we can use to fetch data from Fitbit. ## Using Fitbit's API Fitbit has an [OAuth 2.0 web API](https://dev.fitbit.com/build/reference/web-api/) that you can use. You have to register your application on Fitbit's website to receive a client ID and a client secret to connect to the API. I decided to fetch the Fitbit data using an Express app with node. Fetching the data this way will make it really easy to use on a live website. Node has tons of NPM modules which makes connecting to Fitbit's API relatively easy. I'm using [Passport](http://www.passportjs.org/) which is a common authentication middleware for Express. ```javascript /** express app */ const express = require("express"); /** Manages oauth 2.0 w/ fitbit */ const passport = require('passport'); /** Used to make API calls */ const unirest = require('unirest'); /** express app */ const app = express(); app.use(passport.initialize()); app.use(passport.session({ resave: false, saveUninitialized: true })); var FitbitStrategy = require( 'passport-fitbit-oauth2' ).FitbitOAuth2Strategy; var accessTokenTemp = null; passport.use(new FitbitStrategy({ clientID: config.clientID, clientSecret: config.clientSecret, callbackURL: config.callbackURL }, function(accessToken, refreshToken, profile, done) { console.log(accessToken); accessTokenTemp = accessToken; done(null, { accessToken: accessToken, refreshToken: refreshToken, profile: profile }); } )); passport.serializeUser(function(user, done) { done(null, user); }); passport.deserializeUser(function(obj, done) { done(null, obj); }); passport.authenticate('fitbit', { scope: ['activity','heartrate','location','profile'] }); ``` Since our authentication middlware is all set up, we just need to add the express routes which are required when authenticating. ```javascript app.get('/auth/fitbit', passport.authenticate('fitbit', { scope: ['activity','heartrate','location','profile'] } )); app.get( '/auth/fitbit/callback', passport.authenticate( 'fitbit', { successRedirect: '/', failureRedirect: '/error' })); app.get('/error', (request, result) => { result.write("Error authenticating with Fitbit API"); result.end(); }); ``` Now that we are authenticated with Fitbit, we can finally make queries to Fitbit's Server. I created a helper function called "queryAPI" which attempts to authenticate if it is not already authenticated and then fetches the API result from a provided URL. ```javascript const queryAPI = function(result, path) { return new Promise((resolve, reject)=> { if(accessTokenTemp == null) { result.redirect('/auth/fitbit'); resolve(false); } unirest.get(path) .headers({'Accept': 'application/json', 'Content-Type': 'application/json', Authorization: "Bearer " + accessTokenTemp}) .end(function (response) { if(response.hasOwnProperty("success") && response.success == false) { result.redirect('/auth/fitbit'); resolve(false); } resolve(response.body); }); }); }; app.get('/steps', (request, result)=> { queryAPI(result, 'https://api.fitbit.com/1/user/-/activities/tracker/steps/date/today/1m.json').then((data)=> { if(data != false) { result.writeHead(200, {'Content-Type': 'text/html'}); result.write(JSON.stringify(data)); result.end(); } else { console.log("Validating with API"); } }); }); ``` ## Exporting Data from Website On [Fitbit's website](https://www.fitbit.com/settings/data/export) there is a nice page where you can export your data. ![Fitbit Website Data Export](media/fitbit/fitbitDataExport.png) The on demand export is pretty useless because it can only go back a month. On top of that, you don't get to download any detailed heart rate data. The data that you get is aggregated by day. This might be fine for some use cases; however, this will not suffice for any interesting analysis. I decided to try the account archive option out of curiosity. ![Fitbit Archive Data](media/fitbit/fitbitArchiveData.png) The Fitbit data archive was very organized and kept meticulous records of everything. All of the data was organized in separate JSON files labeled by date. Fitbit keeps around 1MB of data on you per day; most of this data is from the heart rate sensors. Although 1MB of data may sound like a ton of data, it is probably a lot less if you store it in formats other than JSON. Since Fitbit hires a lot of people for hadoop and SQL development, they are most likely using [Apache Hive](https://hive.apache.org/) to store user information on the backend. Distributing the data to users as JSON is really convenient since it makes learning the data schema very easy. # Visualizing The Data Since the Data Archive is far easier, I'm going to start visualizing the data retrieved from the JSON archive. In the future I may use the Fitbit API if I decide to make this a live website. Using R to visualize this would be convenient, however; I want to use some pretty javascript graphs so I can host this as a demo on my website. ## Heart Rate My biggest complaint with Fitbit's website is that they only display your continuous heart rate in one day intervals. If you zoom out to the week or month view, it aggregates it as the number of minutes you are in each heart rate zone. This is fine for the fitbit app where you have limited screen space and no good ways of zooming in and out of the graphs. ![Fitbit Daily Heart Rate Graph](media/fitbit/fitbitDaily.png) ![Fitbit Monthly Heart Rate Graph](media/fitbit/fitBitMonthly.png) I really want to be able to view my heart rate over the course of a few days. To visualize the continuous heart rate I'm going to use [VisJS](http://visjs.org/docs/graph2d/) because it works really well with time series data. To start, I wrote some Javascript which reads the local JSON files from the Fitbit data export. ```html