Мои статистические данные о жизни Я отслеживала свои привычки в течение года, и это то, что я узнала

Мои осознания о жизни, полученные из статистических данных что я узнала, отслеживая свои привычки в течение года

Я измерил время, которое я провел на своих ежедневных занятиях (учеба, занятия спортом, общение, сон…) в течение 332 дней подряд

Почему? Просто почему бы мне это сделать?

Это, наверное, самый длительный и времязатратный эксперимент в моей жизни. Кроме того, он имеет незначительное научное значение — выборка населения состоит всего из одного человека — и является субъективным (он полностью основан на моей памяти и восприятии времени).

Тогда зачем все это делать? Рутины, как и любой другой способ самоотчетности, помогают мне во многих разных ситуациях. Я начал это в периоды падения в своей жизни, пытаясь изучить себя и то, как разные привычки могут влиять на мое настроение и психическое здоровье. Смысл заключался в том, чтобы “взломать” свой собственный мозг: если я знал – статистически — что делает меня счастливым и здоровым в долгосрочной перспективе (и что наоборот!), я смогу улучшить свою жизнь и, возможно, дать советы или помочь людям, проходящим через трудные времена, подобные моим.

А почему бы этот эксперимент не имел значения для вас?

Я считаю, что эта интроспективная практика является отличным примером применения науки о данных к любой сфере. Конечно, это не обязательно должно быть отслеживание и ведение дневника. Вы можете изучать все, что вы считаете ценным в своей жизни: отслеживать поведение своего питомца, погодные условия в вашем городе, задержки в местной системе общественного транспорта… Существует множество анализов, которые можно провести в отношении себя: если есть данные, вы можете изучать их! К счастью, данные повсюду – вам просто нужно посмотреть в нужном месте и проследить за ними.

Метод – что я делал и как делал это?

Я отводил несколько минут каждый день, чтобы делать личные заметки о том, что я делал и отслеживать время, проведенное (в часах) на различных деятельностях и категориях.

Переменные, которые я измерял, немного менялись в течение года: некоторые новые появлялись, некоторые исчезали, а другие объединялись. Окончательными и теми, для которых у меня есть данные для всех записей времени, являются следующие: Сон, Письмо, Учеба, Спорт, Музыка, Гигиена, Языки, Чтение, Общение и Настроение – всего десять переменных, охватывающих, по моему мнению, самые важные аспекты моей жизни.

Первоначальный анализ данных

Сначала я посмотрел на индивидуальные временные ряды для четырех переменных: Сон, Учеба, Общение и Настроение. Я использовал Microsoft Excel, чтобы быстро нарисовать несколько графиков. Они представляют собой ежедневное количество проведенных часов (синий цвет) и скользящую среднюю¹ в течение пяти дней MA(5) (красный цвет), которую я считал хорошим показателем для моей ситуации. Переменная настроения оценивалась от 10 (самое большое!) до 0 (ужасное!).

Что касается данных, содержащихся в сноске каждого графика: общая сумма является суммой значений ряда, среднее значение – арифметическое среднее ряда, STD – стандартное отклонение, а относительное отклонение – отношение STD к среднему значению.

Total: 2361ч. Среднее: 7,1ч. STD: 1,1ч. Относительное отклонение: 15.5% (изображение автора).

Принимая все это во внимание, я достаточно хорошо спал. У меня были трудные дни, как и у всех, но, по-моему мнению, тренд довольно стабильный. Фактически, это одна из наименее изменчивых частей моего исследования.

Total: 589,1ч. Среднее значение: 1,8ч. STD: 2,2. Относительное отклонение: 122% (изображение автора).

Это количество часов, которые я потратил на свою академическую карьеру. Оно часто колеблется — найти баланс между работой и учебой часто означает, что приходится спешить проектами в выходные дни. Однако я все же считаю себя довольным.

Всего: 1440,9 часов. Среднее: 4,3 часа. Стандартное отклонение: 4,7 часов. Относительное отклонение: 107% (изображение автора).

Что касается этой таблицы, все, что я могу сказать, это то, что я удивлен. Общая сумма больше, чем я ожидал, учитывая, что я интроверт. Конечно, в это время в университете также учтены часы, проведенные с коллегами. Что касается изменчивости, стандартное отклонение действительно высокое, что имеет смысл, учитывая сложность налаживания рутины в социализации.

Среднее: 8,0 часов. Стандартное отклонение: 0,9 часа. Относительное отклонение: 11,3% (изображение автора).

Эта серия является наименее изменчивой — относительное отклонение наименьшее среди изученных мной переменных. В целом я доволен наблюдаемой тенденцией. Я считаю, что положительно сохранять достаточно стабильное настроение — а тем более, если оно хорошее.

Корреляционное исследование

После анализа тенденций основных переменных я решил глубже углубиться и изучить потенциальные корреляции² между ними. Поскольку моей целью было создание математической модели и прогнозирование (или по крайней мере объяснение) “Настроение”, корреляции являются важной метрикой для рассмотрения. С их помощью я могу выявить связи, такие как “дни, когда я учусь больше, я сплю меньше”, “я обычно учу языки и музыку одновременно” и т. д.

Перед тем, как перейти к чему-либо еще, давайте откроем файл Python и импортируем некоторые ключевые библиотеки для анализа серий. Обычно я использую псевдонимы для них, так как это общепринятая практика и делает код менее громоздким.

import pandas as pd               #1.4.4import numpy as np                #1.22.4import seaborn as sns             #0.12.0import matplotlib.pyplot as plt   #3.5.2from pmdarima import arima        #2.0.4

Мы проведем два разных исследования по корреляции. Мы рассмотрим коэффициент корреляции Пирсона³ (для линейных взаимосвязей между переменными) и коэффициент корреляции Спирмена⁴ (который изучает монотонные взаимосвязи между переменными). Мы будем использовать их реализацию⁵ в библиотеке pandas.

Матрица корреляции Пирсона

Коэффициент корреляции Пирсона между двумя переменными X и Y вычисляется следующим образом:

где cov - ковариация, sigma X - std(X) и sigma Y - std(Y)

Мы можем быстро вычислить матрицу корреляции, где вычисляется каждая возможная попарная корреляция.

#Чтение, выбор и нормализация данныхraw = pd.read_csv("final_stats.csv", sep=";")numerics = raw.select_dtypes('number')#Вычисление матрицы корреляциипо методу Пирсонаcorr = numerics.corr(method='pearson')#Генерация тепловой картыsns.heatmap(corr, annot=True)#Отрисовка графикапlt.show()

Это исходная матрица корреляций Пирсона, полученная из моих данных.

Матрица корреляции Пирсона для моих переменных (изображение автора).

Вот значимые значения⁶ — те, которые, с 95% уверенностью, отличаются от нуля. Мы выполняем t-тест⁷ с использованием следующей формулы. Для каждого значения корреляции rho мы отбрасываем его, если:

где n – размер выборки. Мы можем использовать код из предыдущего примера и добавить этот фильтр.

#константaN=332 #количество образцовSTEST = 2/np.sqrt(N)def significance_pearson(val):    if np.abs(val)<STEST:        return True    return False#читаем данныеraw = pd.read_csv("final_stats.csv", sep=";")numerics = raw.select_dtypes('number')#вычисляем корреляциюcorr = numerics.corr(method='pearson')#подготавливаем маскиmask = corr.copy().applymap(significance_pearson)mask2 = np.triu(np.ones_like(corr, dtype=bool)) #убираем верхний треугольникmask_comb = np.logical_or(mask, mask2)c = sns.heatmap(corr, annot=True, mask=mask_comb)c.set_xticklabels(c.get_xticklabels(), rotation=-45)plt.show()

Те значения, которые были отброшены, могут быть просто шумом и неправильно отражать тенденции или отношения. В любом случае, лучше считать истинные отношения бессмысленными, чем считать смысловыми те, которые ими не являются (что мы называем предпочтением ошибки второго рода перед ошибкой первого рода). Это особенно верно для исследования с довольно субъективными измерениями.

Фильтрованная матрица корреляции Пирсона. Незначимые значения (и верхний треугольник) были отфильтрованы. (изображение автора)

Коэффициент корреляции рангов Спирмена

Коэффициент корреляции Спирмена может быть вычислен следующим образом:

где R указывает на ранговую переменную⁸ - остальные переменные те же, что и в описании коэффициента Пирсона.

Как и раньше, мы можем быстро вычислить матрицу корреляции:

#читаем, выбираем и нормализуем данныеraw = pd.read_csv("final_stats.csv", sep=";")numerics = raw.select_dtypes('number')#вычисляем матрицу корреляцийcorr = numerics.corr(method='spearman') #обратите внимание на это изменение!#генерируем тепловую картусns.heatmap(corr, annot=True)#рисуем графикplt.show()

Это исходная матрица корреляции Спирмена, полученная из моих данных:

Матрица корреляции Спирмена для моих переменных (изображение автора).

Давайте посмотрим, какие значения фактически значимы. Формула для проверки значимости выглядит следующим образом:

где r - коэффициент Спирмена. Здесь t следует распределению Стьюдента с n-2 степенями свободы.

Здесь мы отфильтруем все значения t, превышающие (по модулю) 1.96. Снова, причина их отбрасывания заключается в том, что мы не уверены, являются ли они шумом – случайностью – или настоящей тенденцией. Давайте закодируем это:

#constantsN=332 #количество выборокTTEST = 1.96def significance_spearman(val):    if val==1:        return True    t = val * np.sqrt((N-2)/(1-val*val))        if np.abs(t)<1.96:        return True    return False#read dataraw = pd.read_csv("final_stats.csv", sep=";")numerics = raw.select_dtypes('number')#calculate correlationcorr = numerics.corr(method='spearman')#prepare masksmask = corr.copy().applymap(significance_spearman)mask2 = np.triu(np.ones_like(corr, dtype=bool)) #remove upper trianglemask_comb = np.logical_or(mask, mask2)#plot the resultsc = sns.heatmap(corr, annot=True, mask=mask_comb)c.set_xticklabels(c.get_xticklabels(), rotation=-45)plt.show()

Вот значимые значения.

Матрица корреляции с значимыми значениями. (изображение автора)

Я считаю, что эта диаграмма лучше объясняет ощутимые взаимосвязи между переменными, так как ее критерий более “естественный” (она учитывает монотонные⁹, а не только линейные, функции и взаимосвязи). Она не так сильно подвержена влиянию выбросов, как другая диаграмма (несколько плохих дней, связанных с определенной переменной, не повлияют на общий коэффициент корреляции).

Тем не менее, я оставлю обе диаграммы для читателей, чтобы они сами могли сделать свои собственные выводы.

Исследования временных рядов – модели ARIMA

Мы можем рассматривать эти данные как временной ряд. Время может быть важным фактором при объяснении переменных: некоторые из них могут колебаться периодически или даже быть автокоррелированными¹⁰. Например, плохая ночь может заставить меня заснуть и вызвать полосы большого сна на следующий день – это будет взаимосвязь в пределах времени. В этом разделе я сосредоточусь только на переменных начального исследования.

Давайте изучим модель ARIMA и найдем хорошую подгонку под наши данные. Модель ARIMA¹¹ является комбинацией авторегрессионной модели (AR¹²) и скользящего среднего, отсюда и ее инициалы (Auto Regressive Integrated Moving Average). В этом случае мы будем использовать метод auto_arima из pmdarima, функцию, вдохновленную функцией “forecast::autoarima” из языка R, чтобы определить коэффициенты для нашей модели.

for v in ['Sleep','Studying','Socializing','Mood']:    arima.auto_arima(numerics[v], trace=True) #trace=True для просмотра результатов

Результаты были обобщены в следующей таблице:

Модели ARIMA(p,d,q) с соответствующими AIC (изображение автора).

Удивительно, что сон не является авторегрессионным, но настроение, кажется, является! Как мы видим, простая модель ARIMA(1,0,0) – AR(1) – достаточно хорошо представляет настроение. Это означает, что настроение в день D объясняется настроением в день D-1, или предшествующим днем, и некоторым нормально распределенным шумом.

Несмотря на то, что это кажется незначительным, это достаточно интересное следствие. Учеба также является авторегрессионной, но следует модели ARIMA(1,0,2) – что означает, что она не прямо следует за трендом, но ее скользящее среднее делает это. Однако AIC¹³ для нее значительно выше, так что возможно, что модель может слишком сложно объяснять наблюдаемое поведение.

FFT – Быстрое преобразование Фурье

Мы можем использовать дискретное преобразование Фурье¹⁴ для анализа наших данных. С его помощью мы должны заметить любые закономерности, касающиеся сезонности. Преобразование Фурье – это операция преобразования данных, способная разложить ряд на его базовые компоненты. Это можно лучше понять на следующей картинке:

Процесс упрощенного преобразования Фурье (изображение автора)

Вот еще один пример: у нас есть сигнал, состоящий из двух синусоидальных функций с частотой 1 и 10 соответственно. После применения преобразования Фурье мы видим это:

Как мы видим, FFT разлагает сигналы на их частотные компоненты (изображение с Wikimedia Commons)

Результатом является график с двумя пиками, один из которых находится в точке x=1, а другой – в точке x=10. Преобразование Фурье найдет базовые компоненты нашего сигнала!

Переведем это в код:

for v in ['Sleep','Studying','Socializing','Mood']:    t = np.arange(0,N,1)    x = numerics[v]    X = np.fft.fft(x)    n = np.arange(0,len(X),1)    T = N    freq = n/T     plt.figure(figsize = (8, 4))    plt.subplot(121)    plt.plot(t, x, 'r')    plt.xlabel('Time (days)')    plt.ylabel(v)    plt.subplot(122)    plt.stem(n, np.abs(X), 'b', markerfmt=" ", basefmt="-b")    plt.xlabel('Freq (1/days)')    plt.ylabel('FFT |X(freq)|')    plt.xlim(0, 30)    plt.ylim(0, 500)    plt.tight_layout()    plt.show()

Вернемся к нашему кейсу, вот результаты, которые выводит наш код:

Слева направо и сверху вниз: графики для Sleep, Studying, Socializing и Mood. (изображение автора)

Мы можем наблюдать, что у Sleep есть значительное значение на частоте 1 – это означает, что данные следуют циклу в 1 день, что не очень полезно. Studying также представляет интересные значения: первые пять приблизительно значительно выше остальных. К сожалению, шум берет верх над ними и над каждым другим графиком – нельзя делать окончательные выводы с уверенностью.

Чтобы противостоять ему, мы фильтруем шум с помощью скользящего среднего. Давайте попробуем снова применить MA(5) и изучить FFT. Код будет почти таким же, за исключением скользящего среднего.

def moving_average(x, w):    return np.convolve(x, np.ones(w), 'valid') / wk = 5for v in ['Sleep','Studying','Socializing','Mood']:    t = np.arange(0,N-k+1,1)    x = moving_average(numerics[v], k)    X = np.fft.fft(x)    n = np.arange(0,len(X),1)    T = N-k+1    freq = n/T    plt.figure(figsize = (8, 4))    plt.subplot(121)    plt.plot(t, x, 'r')    plt.xlabel('Time (days)')    plt.ylabel(v)    plt.subplot(122)    plt.stem(n, np.abs(X), 'b', markerfmt=" ", basefmt="-b")    plt.xlabel('Freq (1/days)')    plt.ylabel('FFT |X(freq)|')    plt.xlim(0, 30)    plt.ylim(0, 500)    plt.tight_layout()    plt.show()

Вот графики, сгенерированные нашим кодом:

Слева направо и сверху вниз: графики для Sleep, Studying, Socializing и Mood. (изображение автора)

После применения МА шум незначительно снизился. Тем не менее, кажется, что из этого нельзя сделать никаких выводов – мы не можем найти значимых четких значений частоты.

Выводы

После проведения различных статистических исследований, мы можем сделать ожидаемые выводы: человеческое поведение очень сложно – более сложно, конечно, чем можно учесть с помощью таблицы Excel и нескольких математических моделей. Тем не менее, есть ценность как в методичном сборе данных, так и в аналитических возможностях, которые возникают в результате этого. Давайте кратко рассмотрим то, что мы сделали:

  • Обзор исходных данных и тренда.
  • Корреляционный анализ Пирсона и Спирмена и тесты значимости.
  • Модель ARIMA.
  • Декомпозиция быстрого/дискретного преобразования Фурье.

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

  • Что касается относительного отклонения (вариабельности), настроение и сон были наименьшими (соответственно 11,3% и 15,5%), в то время как учеба и общение были выше 100%.
  • Обнаружено, что общение имеет отрицательную корреляцию практически со всеми моими увлечениями, но положительную корреляцию с моим настроением (как по Пирсону, так и по Спирмену). Вероятно, это связано с тем, что когда я встречаюсь с друзьями или семьей, я откладываю свои увлечения на один день, но обычно я счастливее, чем в одиночку.
  • Настроение и письмо имели отрицательную корреляцию (по Спирмену), что можно объяснить тем, что иногда я выражаю свои проблемы через короткие рассказы или записи в дневнике.
  • Обнаружено, что настроение и учеба являются авторегрессионными при подгонке модели ARIMA, что означает, что значение в определенный день можно объяснить предыдущим.
  • С помощью дискретного преобразования Фурье не удалось найти четкую декомпозицию, хотя некоторые группы частот превышали другие.

Также стоит отметить, что мы получили интересные “глобальные” статистические показатели, которые, хотя и не имеют научного значения, все же интересно знать.

Лично я считаю, что этот эксперимент был полезным для меня. Даже если окончательные результаты не являются окончательными, я считаю, что это помогло мне справиться с трудными временами и отследить хорошие. Также я считаю, что всегда полезно провести некоторую интроспекцию и лучше узнать себя.

В заключение, вот накопительная диаграмма – снова сделанная в MS Excel – для всех переменных, которые можно суммировать (каждая, кроме настроения и гигиены, которые не измеряются в часах, а в определенном рейтинге; и сон). Я решил построить ее в виде логарифмической диаграммы, потому что, даже если накапливающиеся переменные были линейными, изменяющиеся наклоны затрудняли просмотр данных. Вот и все! Наслаждайтесь!

Накопленная сумма каждой серии, логарифмическая ось Y. (изображение автора)

Как всегда, я призываю вас комментировать любые мысли или сомнения, которые у вас может возникнуть.

Код и данные находятся на моем github.

GitHub – Nerocraft4/habittracker

Сотрудничайте с Nerocraft4/habittracker, создав учетную запись на GitHub.

github.com

References

[1] Википедия. Скользящая средняя. https://en.wikipedia.org/wiki/Moving_average

[2] Википедия. Корреляция. https://en.wikipedia.org/wiki/Correlation

[3] Википедия. Коэффициент корреляции Пирсона. https://en.wikipedia.org/wiki/Pearson_correlation_coefficient

[4] Википедия. Коэффициент ранговой корреляции Спирмена. https://ru.wikipedia.org/wiki/Коэффициент_ранговой_корреляции_Спирмена

[5] Документация Pandas. pandas.DataFrame.corr. https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html

[6] Википедия. Статистическая значимость. https://ru.wikipedia.org/wiki/Статистическая_значимость

[7] Википедия. t-критерий Стьюдента. https://ru.wikipedia.org/wiki/T-критерий_Стьюдента

[8] Википедия. Ранговая корреляция. https://ru.wikipedia.org/wiki/Ранговая_корреляция

[9] Wolfram MathWorld. Монотонная функция. https://mathworld.wolfram.com/MonotonicFunction.html

[10] Википедия. Автокорреляция. https://ru.wikipedia.org/wiki/Автокорреляция

[11] Википедия. Интегрированная авторегрессия скользящего среднего. https://ru.wikipedia.org/wiki/Интегрированная_авторегрессия_скользящего_среднего

[12] Википедия. Авторегрессионная модель. https://ru.wikipedia.org/wiki/Авторегрессионная_модель

[13] Science Direct. Критерий Акаике. https://www.sciencedirect.com/topics/social-sciences/akaike-information-criterion

[14] Википедия. Дискретное преобразование Фурье. https://ru.wikipedia.org/wiki/Дискретное_преобразование_Фурье