Алла Тамбовцева, НИУ ВШЭ
Выделяют четыре основных типа шкал:
Два последних типа часто объединяют и называют количественной шкалой. Позволю себе здесь сослаться на статью в Википедии, там приведено достаточно подробное описание шкал с примерами.
Для оценки связи между двумя переменными в качественной (номинальной) шкале используются таблицы сопряжённости (contingency tables) и критерий хи-квадрат. Оценим связь между двумя показателями из таблицы, содержащей результаты опроса студентов 1 курса НИУ ВШЭ (ОП «Политология»). Опрос был учебным, но с социолингвистическим уклоном: как жители разных регионов называют различные предметы и какие выражения используют.
Идея опроса была навеяна спором на кафедре о том, как называть замазку/корректор/штрих и продолжившимся ещё более жарким спором, как продолжить фразу «жадина-говядина – ...». Оказалось, что коллеги из Москвы не использовали вариант «Жадина-говядина – солёный огурец, на полу валяется, никто его не ест», а коллеги не из Москвы никогда не слышали вариант «Жадина-говядина – турецкий барабан, кто на нём играет, тот рыжий таракан». Студентам опрос пришёлся по душе, правда, в какое-то более серьёзное исследование это не переросло.
На сами вопросы можно посмотреть здесь.
Импортируем библиотеку pandas
и загрузим файл по ссылке:
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/allatambov/R-programming-3/master/exam-23-03/soc_ling.csv",
encoding="UTF-8")
Посмотрим на первые строки таблицы:
df.head()
Построим таблицу сопряжённости для переменных conts
(нормализованное продолжение фразы «жадина-говядина – ...») и region
(родной регион респондента).
pd.crosstab(df.conts, df.region)
Таблица сопряжённости – таблица совместных частот. Например, по таблице выше мы можем выяснить, что чаще всего фразу «жадина-говядина» с «турецким барабаном», действительно, используют студенты из Москвы (9), а один студент из Вологодской области, один студент из Иркутской области и три студента из Якутии предложили вариант со словом «шоколадина».
С такой таблицей работать будет неудобно и не совсем корректно: слишком много ячеек с нулевыми и маленькими частотами. Чтобы этого избежать, укрупним категории, например, объединим все регионы в федеральные округа.
df.region.unique() # все уникальные значения регионов в таблице
Напишем функцию, которая будет приписывать регион к федеральному округу (для простоты возьмём только те регионы, которые есть в df
) и создадим новый столбец okrug
:
def get_okrug(x):
Cent = ['Белгородская область', 'Тверская область', 'ЦО, Москва', 'Москва',
'Московская область', 'Калужская область']
NoWest = ['Вологодская область', 'Республика Коми']
South = ['Волгоградская область']
Privolzh = ['Самарская область', 'Пермский край']
Ural = ['Свердловская область', 'ХМАО-Югра']
Sibir = ['Алтайский край', 'Новосибирская область', 'Иркутская область']
DEast = ['Республика Саха (Якутия)', 'Хабаровский край', 'Приморский край']
Out = ['Молдавия', 'Молдова', 'Узбекистан']
if x in Cent:
ok = 'Центральный'
if x in NoWest:
ok = 'Северо-Западный'
if x in South:
ok = 'Южный'
if x in Privolzh:
ok = 'Приволжский'
if x in Ural:
ok = 'Уральский'
if x in Sibir:
ok = 'Сибирский'
if x in DEast:
ok = 'Дальневосточный'
if x in Out:
ok = "Зарубежные территории"
return ok
df['okrug'] = df.region.apply(get_okrug)
df.head()
Теперь построим таблицу сопряжёенности для переменных conts
и okrug
:
table = pd.crosstab(df.conts, df.okrug)
table
Теперь сформируем из обычной таблицы сопряжённости объект типа Table
из модуля stats
библиотеки statsmodels
, чтобы на её основе можно было проверять гипотезу о независимости двух признаков (переменных в качественной шкале).
from statsmodels.api import stats
cont_table = stats.Table(table)
При выявлении связи между качественными признаками выдвигается следующая нулевая гипотеза: $$ H_0: \text{признаки независимы (связи нет)}. $$
Соответственно, альтернативная гипотеза:
$$ H_1: \text{признаки не являются независимыми (связь есть)}. $$Как происходит проверка такой нулевой гипотезы? Сравниваются частоты, полученные на основе имеющихся данных (которые мы видели в таблице выше) и ожидаемые частоты – частоты, которые имели бы место, если нулевая гипотеза была бы верна. Считаются разности между наблюдаемыми и ожидаемыми частотами, возводятся в квадрат, чтобы учесть отклонения в обе стороны, и нормируются. Далее определяется сумма этих нормированных квадратов разностей (она имеет распределение хи-квадрат с числом степеней свободы равным $(nrows-1)(ncols-1)$), и оценивается, является ли полученное значение типичным для такого распределения хи-квадрат в случае, если нулевая гипотеза верна.
Посмотрим на ожидаемые частоты:
cont_table.fittedvalues
А теперь на остатки – стандартизированные разности между наблюдаемыми и ожидаемыми частотами (имеют стандартное нормальное распределение):
cont_table.resid_pearson
Если большинство остатков выходят за границы типичных для стандартной нормальной величины значений (обычно таковыми считают значения от $-2$ до $2$), то это может служить основанием для отвержения нулевой гипотезы о независимости признаков. Здесь такого не наблюдается. Убедимся в выводе, определив p-value явно:
res = cont_table.test_nominal_association()
res.pvalue
Действительно, на любом конвенциональном уровне значимости (5%, 10%, 1%) нет оснований отвергнуть нулевую гипотезу. То, как студент продолжает фразу «Жадина-говядина» не связано с тем, в каком федеральном округе он жил больше всего. Проверим то же самое, но не для всех округов, а конкретно для разделения Москва-не Москва.
df['moscow'] = df.region == 'Москва'
df.head()
tt = pd.crosstab(df.moscow, df.conts)
cont_table2 = stats.Table(tt)
cont_table2.test_nominal_association().pvalue
В данном случае на имеющихся данных у нас есть основания отвергнуть нулевую гипотезу о независимости признаков на 5% уровне значимости (pvalue<0.05
). Следовательно, можем считать, что тот факт, из Москвы студент или нет, влияет на то, какую форму продолжения фразы о жадине он выбирает.
В теоретической части была подробно описана методика расчёта коэффициентов корреляции Пирсона и Спирмена, а также критерии их применимости, поэтому давайте просто посмотрим, как их вычислять с помощью библиотеки scipy
.
Загрузим уже знакомый по первой части специализации файл с оценками студентов scores2.csv
:
data = pd.read_csv("https://raw.githubusercontent.com/allatambov/CognTech/master/2-python-libraries/scores2.csv")
data.head()
Рассчитаем коэффициент корреляции Пирсона между оценками студентов по математике (mstat
) и статистике (mstat2
).
import scipy.stats as st
st.pearsonr(data.mstat, data.mstat2)
Вспомним, какая гипотеза проверяется при реализации формального критерия:
$H_0:\rho=0$ (связи нет, коэффициент корреляции не является статистически значимым)
$H_1:\rho \ne0$ (связь есть, коэффцициент корреляции является статистически значимым)
Интерпретация: связь положительная и сильная, нулевая гипотеза о незначимости коэффициента корреляции отвергается (на любом конвенциональном уровне значимости), есть значимая связь между оценками по двум частям курса «Математика и статистика».
Однако, в нашем случае для оценки связи между этими переменными уместно всё же выбрать коэффицент корреляции Спирмена, поскольку шкала оценок является порядковой:
st.spearmanr(data.mstat, data.mstat2)
Принципиальных отличий в результатах не наблюдается. Если бы мы хотели оценить (и сразу визуализировать) связь между всеми парами переменных, мы могли бы воспользоваться библиотекой seaborn
и нарисовать тепловую карту – в данном случае корреляционную матрицу с раскрашенными ячейками, интенсивность цвета которых отвечает за силу связи.
Отберём нужные столбцы (все, кроме номера студенческого и пола студента):
small = data.loc[:,'catps' : 'game']
small = small.dropna()
small.corr('spearman') # просто корреляционная матрица
# картинка
import seaborn as sn
sn.heatmap(small.corr('spearman'))
На мой взгляд, будет привычнее, если более высоким значениям коэффициентов корреляции будут соответствовать более тёмные цвет. Изменим палитру:
sn.heatmap(small.corr('spearman'), cmap='Blues')
Про цветовые палитры можно почитать здесь.