Статистика. Часть 2. Меры рассеивания (measures of dispersion)
Published 19 июля 2025 г. 17:16
И снова здравствуйте!
Сегодня мы продолжим наше путешествие по просторам статистики🙂. На этот раз мы рассмотрим меры рассеивания.
Меры рассеивания (mesasures of dispersion) позволяют понять, насколько различны между собой значения в данных (или же степень их неоднородности).
Существует 4 основных меры рассеивания:
- Стандартное отклонение
- Дисперсия
- Размах (или диапазон (range))
- Межквартильный размах (Interquartile range или IQR)
Итак, поехали!
Стандартное отклонение обозначает среднюю величину (или же среднее расстояние) между каждым значением и средней (mean) всего набора данных. Каждое значение в наборе данных отличается от среднего значения всего набора. Когда нам нужно узнать среднюю величину данного отличия, мы используем стандартное отклонение. Например, нам нужно узнать, какой средний разброс по росту (в мм) в холке у собак.
Для начала найдем среднее:
(600 + 500 + 200 + 400 +300) / 5 = 400
Формула стандартного отклонения выглядит следующим образом:
\(\sigma = \sqrt{\frac{1}{N} \sum_{i=1}^{N} (x_i - \overline{x})^2}\)
Небольшой ужастик, да?) На самом деле здесь нет ничего страшного 🙂. Чтобы вычислить стандартное отклонение, необходимо сперва суммировать квадраты разностей между каждым значением набора данных и средним значением всего набора, затем поделить это на количество данных (строк) в нашем наборе и в конце взять квадратный корень от этого числа.
Однако есть и другая формула для вычисления стандарного отклонения!
\(s = \sqrt{\frac{1}{N-1} \sum_{i=1}^{N} (x_i - \overline{x})^2}\)
Различие заключается не только в буквенных обознаениях). Первая формула (с сигмой) предназначена для расчета стандартного отклонения для всей генеральной выборки. То есть в нашем случае для всех песиков в мире(⊙o⊙). Конечно, такие данные мы собрать пока не можем, поэтому мы будем использовать формулу с s.
На нашем примере с собакенами это будет выглядеть следующим образом:
\(s = \sqrt{\frac{1}{5-1} \sum_{i=1}^{5} (x_i - \overline{x})^2} = \sqrt{\frac{1}{4} * (600 - 400)^2 + (500 - 400)^2 + (200 - 400) ^ 2 + (400 - 400) ^ 2 + (300 - 400)^2} \approx 158.11\)
Вот так мы выяснили, что в среднем рост собак в холке отличается от среднего роста в выборке примерно на 158 мм. И теперь код!
Как и в прошлый раз, в коде мы будем использовать данные по средней продолжительности жизни по странам с 1952 года (см. первую часть цикла статей).
# Сперва загрузим данные
import math
import plotly.express as px
df = px.data.gapminder()
data = df[df['year'] == 2007]
gdp_list = data['gdpPercap'].tolist()
def mean(values):
# Вычислим среднее
return sum(values) / len(values)
# И стандартное отклонение
# Обратите внимение, здесь используется формула вычисления стандартного отклонения ДЛЯ ВЫБОРКИ
def std_dev(values):
mu = mean(values)
squared_diffs = [(x - mu) ** 2 for x in values]
variance = sum(squared_diffs) / (len(values) - 1)
return math.sqrt(variance)
Как видно по результатам вычислений, стандартное отклонение очень большое. В данном случае это означает, что существует ряд очень богатых стран, из-за которых происходит смещение в данных относительно среднего значения.
Идём дальше и на очереди у нас дисперсия. Дисперсия - это квадрат стандартного отклонения. То есть формула почти такая же, как и выше, только без квадратного корня:
Для генеральной совокупности:
\(\sigma ^ 2 = \frac{1}{N} \sum_{i=1}^{N} (x_i - \overline{x})^2\)
Для выборки данных:
\(s ^ 2 = \frac{1}{N - 1} \sum_{i=1}^{N} (x_i - \overline{x})^2\)
По правде сказать, дисперсия может показать нам только то, насколько сильно у нас разбросаны значения от среднего, прежде чем мы будем искать стандартное отклонение (в общем случае она и используется для вычисления стандартного отклонения). Немного кода:
# Т.к. у нас уже есть функция для вычисления среднего, то мы можем использовать её для вычисления дисперсии.
# У нас есть только выборка (не генеральная совокупность), поэтому мы будем использовать формулу с 1/(N - 1)
def sample_dispersion(data):
mu = mean(data)
return sum((x - mu) ** 2 for x in data) / (len(data) - 1)
Теперь приступим к размаху (aka range или диапазон). Размах - это разница между наибольшим и наименьшим значением в данных.
ВАЖНО!
Размах очень чувствителен к выбросам (это нужно учитывать при интерпретации его значения).
Формула предельно проста:
\(Range=max(x)−min(x)\)
Снова код (для любителей есть и вариант без встроенных функций 🙃):
# Вариант №1 - не заморачиваемя и используем встроенные функции
gdp_range = max(gdp_list) - min(gdp_list)
print("GDP Range:", gdp_range)
# Вариант №2 - ХАРДКОД для поиска наибольшего и наименьшего значений в данных с помощью цикла 😈
def data_range(values):
minimum = values[0]
maximum = values[0]
for val in values[1:]:
if val < minimum:
minimum = val
if val > maximum:
maximum = val
return maximum - minimum
+ график
import matplotlib.pyplot as plt
plt.hist(gdp_list, bins=20, color='lightgreen', edgecolor='black')
plt.axvline(min(gdp_list), color='red', linestyle='dashed', label='Min')
plt.axvline(max(gdp_list), color='blue', linestyle='dashed', label='Max')
plt.title("GDP по столицам со стандартным отклонением")
plt.xlabel("GDP по столицам")
plt.ylabel("Частота")
plt.legend()
plt.grid(True)
plt.show()
И наконец неизвестный (пока) нам межквартильный размах (Interquartile range или IQR)! Звучит грозно, но в понимании он достаточно простой). Он позволяет нам понять, в каком диапазоне лежит 50% наших данных. По формуле:
\(IQR=Q_3−Q_1 \)
межквартильный размах представляет собой разность между третьим и первым квартилем. Квартиль - это статистический показатель, который делит упорядоченный набор данных на 4 равные части. По факту перед межквартильным размахом у нас будет 25% данных и после него тоже 25% данных.
По своим свойствам межквартильный размах устойчив к выбросам и смещениям данных, поэтому является лучшей альтернативой обычному размаху.
CODE TIME!
# Тут мы всё же используем модуль math, чтобы найти квартили.
# Небольшая ремарка по названию функции - percentile.
# Процентили делят упорядоченные данные на сто равных частей.
# Квартили — это процентили, которые делят набор данных на четверти.
# Первый квартиль, Q1, равен 25-ому процентилю, третий квартиль, Q3, равен 75-ому процентилю.
import math
def percentile(values, p):
sorted_vals = sorted(values)
k = (len(sorted_vals) - 1) * (p / 100)
f = math.floor(k)
c = math.ceil(k)
if f == c:
return sorted_vals[int(k)]
return sorted_vals[f] + (sorted_vals[c] - sorted_vals[f]) * (k - f)
q1 = percentile(gdp_list, 25)
q3 = percentile(gdp_list, 75)
iqr = q3 - q1
print(f"Q1 (25-й процентиль): {q1}")
print(f"Q3 (75-й процентиль): {q3}")
print(f"IQR: {iqr}")
Тут тоже можно график красивый нарисовать)
import matplotlib.pyplot as plt
plt.boxplot(gdp_list, vert=False)
plt.title("GDP по столицам (2007) - Boxplot с IQR")
plt.xlabel("GDP для столицы")
plt.grid(True)
plt.show()
Тут видно, что наши данные сильно смещены влево, значит большинство стран имеет достаточно низкий GDP. Также этот график позволяет нам выявить выбросы (что полезно при дальнейшей обработке данных).
Что ж, думаю, на сегодня статистики хватит). Пора и отдохнуть ~( ̄▽ ̄)~* (заодно переварить новые знания). Код статьи доступен здесь.
До новых встречь!