Details for fitbit_ActivitiesAnalysis.ipynb

Published by Wenqiu999

Description

Activities analysis based on Fitbit data

0

Tags & Data Sources

fitbit connection activities Fitbit Connection

Comments

Please log in to comment.

Notebook
Last updated 3 days, 3 hours ago

This notebook is created to analyze activities data collected by fitbit. It used public data as a demonstrate to show how the plots look like.

You can use the code below to analyze your own activities data. And This notebook is free to reuse and adapt, distributed under an MIT license: https://opensource.org/licenses/MIT

In [1]:
import pandas as pd
import json
import numpy as np
import matplotlib.pyplot as plt
import seaborn
import urllib
import requests
import os
import tempfile
from datetime import datetime
import seaborn as sns


user_details = api.exchange_oauth2_member(os.environ.get('OH_ACCESS_TOKEN'))
for i in user_details['data']:
    if i['basename'] == 'fitbit-data.json' and i['source'] == 'direct-sharing-102':
        fitbit = requests.get(i['download_url']).json()

'''
data = requests.get('https://www.openhumans.org/api/public/project/102/datafiles/').json()
for i in data['results']:
    if i['id'] == 9135000:
        fitbit = requests.get(i['download_url']).json()
'''
In [2]:
DateTime = []

You can choose the year you want to explore. And extract the activities data out of the fitbit data.

In [3]:
year = '2018'
In [4]:
def GetData(obj,year,key):
    name = key.split('-')[-1]
    name = []
    for day in fitbit[obj][year][key]:
        name.append(day['value'])
    return name

for day in fitbit['minutes-to-sleep'][year]['sleep-minutesToFallAsleep']:
    DateTime.append(datetime.strptime(day['dateTime'],'%Y-%m-%d'))
In [5]:
DateTime = pd.DataFrame(DateTime)
In [6]:
activitiesData = pd.DataFrame(
    data = {
        'minutesLightlyActive': GetData('tracker-minutes-lightly-active',year,'activities-tracker-minutesLightlyActive'),
        'minutesSedentary': GetData('tracker-minutes-sedentary',year,'activities-tracker-minutesSedentary'),
        'steps': GetData('tracker-steps',year,'activities-tracker-steps'),
        'calories': GetData('tracker-calories',year,'activities-tracker-calories'),
        'weight': GetData('weight',year,'body-weight'),
        'elevation': GetData('tracker-elevation',year,'activities-tracker-elevation') ,
        'distance': GetData('tracker-distance',year,'activities-tracker-distance'),
        'minutesFairlyActive': GetData('tracker-minutes-fairly-active',year,'activities-tracker-minutesFairlyActive') ,
        'minutesVeryActive': GetData('tracker-minutes-very-active',year,'activities-tracker-minutesVeryActive') ,
        'floors': GetData('tracker-floors',year,'activities-tracker-floors') 

        
    }
)
In [7]:
activitiesData = pd.concat([DateTime, activitiesData], axis=1)
activitiesData.rename(columns={activitiesData.columns[0]: 'DateTime'}, inplace=True)
activitiesData = activitiesData.set_index('DateTime', drop= False)

There might be some days when your device failed to collect your data. Let's remove the dates that data were not collected first.

In [8]:
col = ['floors','minutesLightlyActive','minutesSedentary','steps','calories','weight','elevation','distance','minutesFairlyActive','minutesVeryActive']
activitiesData[col] = activitiesData[col].mask(activitiesData[col].applymap(str).eq('0'))
In [9]:
activitiesData[['weight','minutesLightlyActive', 'steps', 'minutesSedentary', 'calories', 'elevation','distance','minutesFairlyActive','minutesVeryActive','floors']] = activitiesData[['weight','minutesLightlyActive', 'steps', 'minutesSedentary', 'calories', 'elevation','distance','minutesFairlyActive','minutesVeryActive','floors']].astype(float)
activitiesData['Day of week'] = activitiesData.index.weekday_name
weekday = ['Monday','Tuesday','Wednesday','Thursday','Friday']
weekend = ['Saturday','Sunday']
activitiesData.loc[activitiesData['Day of week'].isin(weekday), 'IsWeekday'] = 'Weekday'
activitiesData.loc[activitiesData['Day of week'].isin(weekend), 'IsWeekday'] = 'Weekend'
dayGroupedData = activitiesData.groupby(['Day of week']).mean()
dayTypeGroupedData = activitiesData.groupby(['IsWeekday']).mean()

Now we can start with descriptive analysis of the variables in your activities data.

In [10]:
activitiesData[['weight','minutesLightlyActive', 'steps', 'minutesSedentary', 'calories', 'elevation','distance','minutesFairlyActive','minutesVeryActive','floors']] = activitiesData[['weight','minutesLightlyActive', 'steps', 'minutesSedentary', 'calories', 'elevation','distance','minutesFairlyActive','minutesVeryActive','floors']].astype(float)
cols = ['steps', 'minutesSedentary', 'calories', 'elevation','distance','floors']
activitiesData[cols].describe()
Out[10]:
steps minutesSedentary calories elevation distance floors
count 355.000000 365.000000 365.000000 354.000000 365.000000 354.000000
mean 12675.504225 745.432877 3296.857534 104.841808 9.316905 34.559322
std 3256.557970 153.477202 437.778077 73.933305 2.880027 24.253457
min 19.000000 429.000000 1831.000000 3.000000 0.000000 1.000000
25% 11042.000000 677.000000 3069.000000 51.000000 8.288960 17.000000
50% 12790.000000 728.000000 3318.000000 91.000000 9.656330 30.000000
75% 14245.000000 777.000000 3555.000000 128.000000 10.676750 42.000000
max 25082.000000 1440.000000 5829.000000 448.000000 19.754160 147.000000

Let's explore the weekly pattern within the data first.

In [11]:
fig,axes = plt.subplots(nrows=2, ncols=3,figsize=(15, 15))
dayofweek = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun']
data_plot = list()
for i in range(len(axes)):
    for j in range(len(axes[i])):
        data_plot.append(axes[i][j])
for i,(x,ax) in enumerate(zip(cols,data_plot)):
    ax = activitiesData.groupby('Day of week')[x].mean().plot(kind='bar', ax = data_plot[i])
    ax.set_title('Average {} over a week in {}'.format(x, year))
    ax.set_xticklabels(dayofweek, rotation = 0, ha="right")
    ax.xaxis.label.set_visible(False)
plt.suptitle('Figure 1. Weekly Pattern of Activities in {}'.format(year))
plt.show()

There are 3 different levels of activity. Let's take a look at these levels.

In [12]:
cols_level = ['minutesLightlyActive', 'minutesFairlyActive','minutesVeryActive']
activitiesData[cols_level].describe()
Out[12]:
minutesLightlyActive minutesFairlyActive minutesVeryActive
count 355.000000 351.000000 349.000000
mean 174.087324 40.777778 62.063037
std 43.910357 19.877242 24.336873
min 2.000000 5.000000 4.000000
25% 144.000000 27.000000 47.000000
50% 171.000000 38.000000 61.000000
75% 197.000000 52.000000 77.000000
max 365.000000 124.000000 158.000000
In [13]:
fig = plt.figure(figsize = (6,6))
labels=['LightActive', 'FairlyActive','VeryActive']
plt.pie(activitiesData[cols_level].mean(), colors = ['lightskyblue', 'yellowgreen','salmon'], autopct='%1.1f%%', labels=labels, textprops=dict(color="w"))
plt.title('Figure 2. Levels of activity', fontsize=14)
plt.legend()
plt.show()

The pie chart above represents the distribution of your active levels over a year.

Do these levels vary based on different days?

In [14]:
fig = plt.figure(figsize = (15,8))
plt.bar((dayGroupedData.index), dayGroupedData['minutesFairlyActive'],  width = 0.4, alpha =0.5, color='dodgerblue', label='Minutes Fairly Active')
plt.bar((dayGroupedData.index), dayGroupedData['minutesVeryActive'], width = 0.4, alpha =0.5, color='slateblue', label='Minutes Very Active', )
plt.bar((dayGroupedData.index), dayGroupedData['minutesLightlyActive'],width = 0.4, alpha =0.5, color='lightskyblue', label='Minutes Lightly Active')
plt.xticks(np.arange(len(dayofweek)),dayofweek)
plt.title('Figure 3. Active Levels Based on Day of the Week')
plt.legend()
plt.show()

The bar chart above shows how your levels of activities differ based on day of the week.

Then, let's take a look at whether you activities vary on weekends vs weekdays?

In [15]:
fig,axes = plt.subplots(nrows=2, ncols=3,figsize=(15, 15))
data_plot = list()
for i in range(len(axes)):
    for j in range(len(axes[i])):
        data_plot.append(axes[i][j])
for i,(x,ax) in enumerate(zip(cols,data_plot)):
    ax = activitiesData.boxplot(column = x, by = 'IsWeekday', vert = True, ax = data_plot[i])
    ax.set_title('Average {} over a week in {}'.format(x, year))
    ax.set_title(x)
    ax.xaxis.label.set_visible(False)
plt.suptitle('Figure 4. Boxplot grouped by Weekday VS Weekend')
plt.show()

The boxplots above show the differences between weekdays and weekends.

Now, let's explore if there is any monthly pattern of your activities.

In [16]:
activitiesData['Month'] = activitiesData.index.month
In [17]:
fig, axes = plt.subplots(3, 1, figsize=(12,10), sharex=True)
for name, ax in zip(cols, axes):
    sns.boxplot(data=activitiesData, x='Month', y=name, ax=ax)
    ax.set_ylabel('Minutes')
    ax.set_title(name)
    if ax != axes[-1]:
        ax.set_xlabel('')
plt.suptitle('Figure 5. Monthly Activities over {}'.format(year))
plt.show()
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)
/opt/conda/lib/python3.6/site-packages/seaborn/categorical.py:454: FutureWarning: remove_na is deprecated and is a private function. Do not use.
  box_data = remove_na(group_data)

Are there any correlations among your activities or the levels of your activity?

In [18]:
correlations = activitiesData[['minutesLightlyActive', 'minutesFairlyActive','minutesVeryActive','steps', 'minutesSedentary', 'calories', 'elevation','distance','floors']].corr()
mask = np.zeros_like(correlations, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
fig = plt.figure(figsize=(15,15)) 
sns.heatmap(correlations,cmap=plt.cm.Greys, mask=mask, linewidths=0.05,vmax=1, vmin=0 ,annot=True,annot_kws={'size':10,'weight':'bold'})
plt.xticks(rotation=45)
plt.suptitle('Figure 6. Activities correlations')
plt.show()
In [ ]: