Анализируем посещения фитнес-клуба

Vladislav Kooklev
4 min readJan 23, 2018

--

Краткий рассказ о том, как я решил собрать метрики своих тренировок.

Вступление

Недавно я установил приложение своего фитнес клуба. Приметил для себя там раздел с историей посещений. Там была дата и продолжительность всех моих тренировок за последние полтора года.

«А из всего это получатся крутые графики»

В то же время я проходил курс по анализу данных. И не долго думая, я решил собрать статистику по этим визитам.

Добываем данные

Я надеялся обойтись без использования мобильного приложения. Зашел на сайт фитнес клуба и обнаружил аналогичную страницу со статистикой. Страница посещений рендерилась напрямую с сервера. Никакое API там не использовалось, а мне совсем не хотелось вытягивать данные из HTML.

У меня был уже опыт сниффинга мобильных приложений через Charles. Он уже был настроен у меня на компьютере. О том, как это сделать есть достаточно информации в интернете. В будущем возможно и сам об этом напишу. Включил в телефоне прокси, открыл историю посещений в приложении, и вот оно.

Скриншот программы Charles

Метод API на получение истории посещений. Авторизация производится через private-key в заголовке. В теле запроса только два параметра. Один передает начальную, а другой конечную дату для поиска. Никаких лимитов я не обнаружил. И вытащил всю историю посещений одним запросом. Посещений набралось аж 163.

Очищаем данные

Объекты посещения содержали много ненужной для меня информации. Меня интересовали только поля с датой и продолжительностью. Пришло время использовать python. С помощью генератора списков я убрал все лишнее. И сохранил в новый массив filtered.

filtered = [{'dt': v['visitTime'], 'duration': v['visitDuration']} for v in visits]

Встроенные списки неудобно анализировать. Для этого лучше подходят датафреймы из библиотеки pandas. Я преобразовал массив в него, и сохранил в .csv файл для дальнейшего использования.

import pandas as pd
df = pd.DataFrame.from_dict(filtered, orient='columns')
df.to_csv('visits.csv')

Вызвал метод df.info() и получил информацию о своем фрейме.

Одинаковое количество значений, пропущенных данных нет. Проверил на дубликаты по дате и времени посещения через df.duplicated(). Их тоже не нашлось.

Теперь мне предстояло проверить данные на наличие outliers. Хорошего русского перевода у этого термина нет. Он означает обособленно стоящие данные. Которые могут негативно влиять на среднее значение. В моем случае они попали в таблицу из-за какой-то ошибки на стороне фитнес клуба.

Я легко заметил на гистограмме колонки с продолжительностью:

df['duration'].hist()

Кроме очевидной погрешности справа, я решил отфильтровать все значения меньше 40 минут. Эти значения тоже могли попасть в таблицу только по ошибке. Составляем запрос для фильтрации и изменяет датафрейм.

clean_df = np.logical_and(df['duration'] > 40, df['duration'] < 400)
df = df[clean_df]

Количество значений сократилось до 158.

Изменяем и дополняем данные

В самом начале я обратил внимание, что столбец даты и времени хранится в формате объекта. Для более удобного анализа перевел его в формат datetime

df['dt'] = pd.to_datetime(df['dt'])

Благодаря этому изменению я легко смог добавить новые поля в таблицу: день недели, месяц, час посещения для будущего анализа.

df['weekday'] = df['dt'].dt.dayofweek
df['month'] = df['dt'].dt.month
df['hour'] = df['dt'].dt.hour

Для большей чистоты устанавливаем дату и время, как индекс таблицы

df = df.set_index('dt')

Много полей не бывает. Добавил еще поле для выходных дней

df['holiday'] = np.array([True if weekday == 5 or weekday == 6 else False for weekday in df['weekday']])

Заканчиваем здесь очистку данных и можем приступать к самому интересному — анализу.

Анализируем данные

Начинаю с базового анализа. Применю к колонке с продолжительностью базовый статистический метод describe.

df['duration'].describe()

Из него узнаю, что средняя продолжительность тренировки 113 минут. Максимальная 243, минимальная 48. Метод отдает и другие статистические данные, но они не так интересны.

Есть еще один метод для определения самых частых значений

df.mode()

Отсюда узнает, что больше всего посещений по месяцу — в марте, по дням недели — в среду, а по часов — с 10 до 11.

Пока немного скучновато, не так ли? Давайте построим графики. Например

scatter plot с зависимостью продолжительности от дня недели.

sns.swarmplot(x=df['weekday'], y=df['duration'], scatter=True)
0 — понедельник. 6 — воскресенье.

Уже интереснее, видим, что тренировки на выходных можно пересчитать на пальцах. А что если вместо дня недели подставить месяц?

sns.swarmplot(x=df['month'], y=df['duration'])
1 — январь. 12 — декабрь.

Очень интересный график. Заметный спад количества тренировок и их продолжительности с окончанием лета. И их увеличение с его же приближением.

Теперь давайте построим что-нибудь для диаграммы самых популярных часов посещений.

sns.swarmplot(x=df['weekday'], y=df['hour'])
0 — понедельник. 6 — воскресенье.

Никакой час особо не выделяется. Но намного чаще у меня были тренировки в первой половине дня.

Заключение

Анализировать данные можно бесконечно. И для любого из значений можно построить много разных графиков. Я не утверждаю, что мой метод анализа данных правильный. Я лишь показываю, как средствами одного Python можно превратить разные части свой жизни в статистику и графики.

Если эта тема будет вам интересна, то продолжу раскрывать её в других постах.

Понравилась статья? Похлопайте в ладоши возле поста.
А также подписывайтесь на мой канал в телеграме.

--

--