Применение коэффициента корреляции Пирсона на примере анализа влияния солнечной активности на уровень криминала в Python

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

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Давно известно, что солнечная активность и, как ее следствие, геомагнитные бури на Земле, оказывают влияние на здоровье и самочувствие людей. И раз так, то возникает закономерный вопрос: может быть солнечная активность как-то влияет и на количество совершаемых преступлений? Типа взяла геомагнитная буря повоздействовала на человека и сподвигла/не сподвигла его совершить противоправные действия.

По ходу повествования поищем связь между двумя количественными переменными (солнечная активность и количество преступлений), определим, какие статистические методы (параметрические или непараметрические) нужно использовать, применим коэффициент корреляции и интерпретируем результаты.

Для начала немного теории по предмету исследования. Геомагнитная буря - это сильные и быстрые изменения в магнитном поле Земли, возникающие в периоды повышенной солнечной активности. Солнечная активность – это процессы в солнечной атмосфере, связанные с образованием и распадом сильных магнитных полей. Для оценки солнечной активности принято использовать два индикатора - число и параметры солнечных пятен и уровень радиоизлучения на длине волны 10.7 см. При этом мощность потока радиоизлучения Солнца на длине волны 10.7 см хорошо коррелирует с суммарной площадью солнечных пятен и уровнем ультрафиолетового излучения. Поэтому для анализа влияния солнечной активности на уровень криминала для целей данной статьи используется этот второй параметр – мощность потока радиоизлучения.

Данные измерений потока радиоизлучения публикуются на сервере сервиса космической погоды Канады , где и был взят набор данных для текущего анализа. Загруженные данные о среднемесячных по годам значениях солнечного потока на длине волны 10,7 см содержат значения наблюдаемого (observed) потока, скорректированного (adjusted) к расстоянию от Земли до Солнца в 1 А.Е. потока, абсолютного (приведенного к абсолютной радиоастрономической шкале URSI, равное 0.9xF10.7) потока.

Набор данных о количестве преступлений за 2003-2020 гг. в России взят на Kaggle здесь.

Анализ проводится на Python в Jupyter Notebook.

1. Загрузка и предобработка данных

Импортируем необходимые библиотеки:

import pandas as pd
from datetime import date
import numpy as np
from scipy import stats
import scipy
import seaborn as sns
import matplotlib.pyplot as plt   
%matplotlib inline
import statsmodels.api as sm
from scipy.stats import norm
import pylab

Считываем набор данных о солнечной активности, который был предварительно сохранен в xls-файл и немного приведен в порядок (запятые в числах заменены на точки, поправлены названия колонок):

sun_ac = pd.read_excel('Sun.xlsx')
sun_ac.head()

Год и месяц в датафрейме (далее df) имеют целочисленный тип данных, но нам нужен формат даты, чтобы потом объединить по этому столбцу со вторым df. Создаем новую колонку с датой из двух имеющихся:

sun_ac['full_date'] = pd.to_datetime(sun_ac.Год.astype(str) + '/' + sun_ac.Месяц.astype(str) + '/01')
sun_ac.head(10)

Считываем набор данных о криминале, указывая в параметрах, что столбец «month» нужно считывать, как дату:

crime_df = pd.read_csv('crime.csv', parse_dates=['month'],  dayfirst=True)
crime_df.tail()

Поскольку оба набора содержат неодинаковый интервал дат, отбираем только тот, который содержится и в том и в другом df. Заодно, проверяем df.shape-ом, что не ошиблись и количество строк одинаковое:

sun_1 = sun_ac.query('full_date >= "2005-01-01" & full_date <= "2019-12-01"')
sun_1.shape
crime_1 = crime_df.query('month >= "2005-01-01" & month <= "2019-12-01"')\
        .rename(columns={'month' : 'full_date'})
crime_1.shape

Объединяем два df, заодно переименовывая колонки на всем понятный язык:

full_df = pd.merge( crime_1, sun_1, on = 'full_date')\
    .rename(columns={'Total_crimes': 'Всего_преступлений',
                     'Serious': 'Тяжкие',
                     'Huge_damage': 'Причинение_ущерба',
                     'Ecological': 'Экологические',
                     'Terrorism': 'Терроризм',
                     'Extremism' : 'Экстремизм',
                     'Murder': 'Убийство',
                     'Harm_to_health': 'Вред_здоровью',
                     'Rape': 'Насилие',
                     'Theft': 'Кражи',
                     'Vehicle_theft': 'Угон_авто',
                     'Fraud_scam': 'Мошенничество',
                     'Hooligan': 'Хулиганство',
                     'Drugs': 'Наркотики',
                     'Weapons': 'Оружие'})
full_df.head()

2. Анализ данных

Собственно, в ходе анализа нам нужно выяснить, имеют ли какую-либо взаимосвязь переменные «Всего_преступлений» и «Абсолютный_поток», и, если имеют, то насколько она сильная. При этом «Всего_преступлений» является зависимой переменной, а «Абсолютный поток» - независимой.

Построим пару графиков, чтобы присмотреться к данным. Это будет лайнплот для переменных «Всего_преступлений» и «Абсолютный_поток» и скаттерплот:

sns.lineplot(data=full_df, x="full_date", y='Всего_преступлений')
sns.lineplot(data=full_df, x="full_date", y='Абсолютный_поток')
plt.scatter(x =full_df.Всего_преступлений, y=full_df.Абсолютный_поток)
plt.show()

Также сгруппируем средние значения этих двух переменных по годам для сопоставления этих средних:

full_df.groupby('Год')\
	.agg({'Всего_преступлений': 'mean', 'Абсолютный_поток': 'mean'})\
	.sort_values('Всего_преступлений', ascending=False)

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

Обе наши переменные – количественные, значит можно задействовать метод корреляции - метод измерения взаимосвязи между двумя количественными переменными, и нахождение коэффициента корреляции. Но для начала следует выяснить, какими данными мы оперируем, потому что   важным моментом принятия решения при работе с выборкой данных является использование параметрических или непараметрических статистических методов. Параметрические статистические методы предполагают, что данные имеют известное и специфическое распределение, часто распределение Гаусса. Если выборка данных не является гауссовой, то предположения о параметрических статистических тестах нарушаются, и должны использоваться непараметрические статистические методы.

Существует несколько методов проверки того, соответствует ли переменная нормальному распределению. Мы задействуем построение гистограмм, график QQ Plot и тест Шапиро-Уилка.

Гистограммы:

plt.hist(full_df.Всего_преступлений)
plt.show()

plt.hist(full_df.Абсолютный_поток)
plt.show()
/
/

Распределение на гистограммах как-то совсем не походит на нормальное.

График QQ Plot:

sm.qqplot(full_df.Всего_преступлений)
pylab.show()

sm.qqplot(full_df.Абсолютный_поток)
pylab.show()

Имеем равномерное распределение, так как в отличие от нормального, точки не следуют по одной прямой. Равномерное распределение имеет много наблюдений в обоих концах. По результатам на графике распределение можно «подтянуть» к нормальному.

Ну и сам тест Шапиро-Уилка. В основе проверки на «нормальность» также лежит
проверка гипотез. Нулевая гипотеза – данные распределены нормально,
альтернативная гипотеза – данные не имеют нормального распределения. Результат
теста Шапиро-Уилка возвращает значение вычисленной статистики и p-значение. В
качестве критического значения в большинстве случаев берется 0.05. При
p-значении меньше 0.05 мы вынуждены отклонить нулевую гипотезу.

w, pvalue = stats.shapiro(full_df.Всего_преступлений)
w, pvalue

w, pvalue = stats.shapiro(full_df.Абсолютный_поток)
w, pvalue

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

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

Сформулируем нулевую и альтернативную гипотезы:

- Н0 – две переменные независимы (нет никакой связи между переменными);

- Н1 – существует зависимость между переменными (существует связь).

Вычисляем:

from scipy.stats import pearsonr
corr, p = pearsonr(full_df.Всего_преступлений, full_df.Абсолютный_поток)
corr, p

Полученное р-значение больше 0,05, следовательно, мы не можем отклонить нулевую гипотезу и делаем вывод, что корреляция статистически незначима и связи между переменными нет. Или другими словами: уровень солнечной активности никак не влияет на уровень преступности.

Однако, это еще не всё. Выше было исследовано влияние солнечной активности на общее количество преступлений, но исследуемые данные также содержат сведения по видам преступлений. «За кадром», дабы не делать статью излишне длинной, был проведен анализ влияния солнечной активности на каждый вид криминала. Так вот, статистически значимый результат показали: «Угон_автомобилей» (corr = 0,2 , р = 0,006), «Наркотики»  (corr = 0,246 , р = 0,0008), «Оружие» (corr = -0,22 , р = 0,002). Что тут можно сказать? Периоды повышенной солнечной активности своеобразным образом сказываются на некоторых людях, которым в такие моменты хочется «закинуться» и свалить в закат на автомобиле, за неимением своего – на угнанном )) Причем без оружия.

Источник: https://habr.com/ru/post/659155/


Интересные статьи

Интересные статьи

В бытовом языке этот фразеологизм означает нечто заумное, переусложненное и бесполезное. Выражение восходит к роману писателя Германа Гессе, за который тот получил Нобелевскую премию. Сегодня мы попро...
Есть много статей, объясняющих, для чего нужен Python GIL (The Global Interpreter Lock) (я подразумеваю CPython). Если вкратце, то GIL не даёт многопоточному чистому коду на Python ис...
Привет, Хабр! Это мой первый опыт с микроконтроллерами в целом, и ESP8266 (в виде Nodemcu v2) в частности. Возможно, для кого-то этот опыт окажется полезным. Почему именно micropython? Отв...
Привет, Хабр. В своей предыдущей статье я рассказал о возможности доступа к методам раздела messages через документацию, для чего достаточно было лишь авторизоваться на сайте ВК. Многие тогда зая...
Привет, Хаброжители! «Путь Python» позволяет отточить ваши профессиональные навыки и узнать как можно больше о возможностях самого популярного языка программирования. Вы научитесь писать эффекти...