Модуль statistics в Python: обработка данных с примерами кода
Пройдите тест, узнайте какой профессии подходите
Для кого эта статья:
- начинающие и опытные разработчики на Python, заинтересованные в аналитике данных
- специалисты в области обработки данных, статистики и машинного обучения
студенты и обучающиеся на курсах по программированию и аналитике данных
Анализ данных часто воспринимается как сложная область, требующая глубоких знаний математики и специализированного ПО. Однако Python разрушает этот стереотип благодаря модулю
statistics
– компактному, но мощному инструменту из стандартной библиотеки. Этот модуль становится незаменимым союзником для тех, кто работает с числовыми данными и не хочет перегружать свой код сложными библиотеками вроде NumPy или Pandas для простых статистических операций. 🧮 Рассмотрим, как эффективно использовать этот инструмент в повседневных задачах анализа данных.
Освоить модуль
statistics
можно гораздо быстрее в рамках практических заданий! Курс «Python-разработчик» с нуля от Skypro предлагает глубокое погружение в статистические инструменты Python через реальные проекты. Вы научитесь не просто применять функции модуля, но создавать полноценные аналитические решения, используя лучшие практики статистического анализа. Курс формирует востребованные навыки обработки данных, которые высоко ценятся работодателями в 2025 году.
Возможности модуля statistics в Python для анализа данных
Модуль statistics
, введённый в Python 3.4, предоставляет мощные инструменты для статистических вычислений, не требуя установки дополнительных библиотек. Это делает его идеальным выбором для быстрого анализа данных, особенно когда нужна базовая статистика без избыточного функционала.
Александр Петров, руководитель отдела аналитики
Долгое время я использовал NumPy для всех статистических операций, даже самых простых. Однажды работал над проектом с ограниченными ресурсами серверной инфраструктуры, где каждый мегабайт зависимостей имел значение. Тогда я обнаружил модуль
statistics
. Заменив тяжеловесный NumPy на встроенный модуль в тех частях кода, где требовались лишь базовые операции, мы сократили размер окружения на 40% и ускорили запуск микросервисов анализа данных почти вдвое. С тех пор я следую принципу: "Не используй ядерную боеголовку, когда достаточно спички" — это стало девизом нашей команды при выборе инструментов анализа.
Основные преимущества модуля statistics
:
- Стандартная библиотека: нет необходимости в установке дополнительных пакетов
- Низкий порог вхождения: простой и понятный интерфейс для базовых операций
- Эффективность: оптимизирован для работы с небольшими и средними наборами данных
- Числовая стабильность: алгоритмы разработаны с учетом минимизации ошибок округления
- Поддержка разных типов данных: работает с целыми числами, числами с плавающей точкой и дробями
Структура и основные категории функций модуля statistics
:
Категория | Функции | Назначение |
---|---|---|
Меры центральной тенденции | mean(), median(), mode() | Определение "типичных" значений в наборе данных |
Меры разброса | variance(), stdev(), pvariance() | Измерение степени разброса данных относительно среднего |
Корреляция | correlation(), covariance() | Измерение связи между переменными (с Python 3.10) |
Квантили | quantiles() | Разбиение данных на равные части (с Python 3.8) |
Важно понимать, что хотя модуль statistics
не заменяет специализированные библиотеки для продвинутого анализа данных, он отлично подходит для быстрых вычислений и прототипирования, особенно в случаях, когда:
- Нужно провести базовый анализ без лишних зависимостей
- Разрабатываются скрипты для использования на разных платформах
- Требуется минимизировать размер пакета или приложения
- Анализ данных не является основной задачей программы
С выходом каждой новой версии Python модуль statistics
пополняется новыми функциями. Например, в Python 3.10 (2021 год) добавлена поддержка функций корреляции, а в Python 3.8 введены функции для работы с квантилями. Это делает модуль всё более универсальным инструментом для статистического анализа. 📊

Базовые статистические функции и их применение
Модуль statistics
предоставляет основные функции для описательной статистики, которые используются для первичного анализа данных. Рассмотрим наиболее востребованные из них с практическими примерами.
Меры центральной тенденции
Эти функции позволяют найти "среднее" или "типичное" значение в наборе данных:
import statistics as stats
# Набор данных о ежедневных продажах за неделю
sales_data = [1200, 1500, 1100, 1800, 1300, 2100, 1400]
# Среднее арифметическое (сумма всех значений, делённая на их количество)
mean_sales = stats.mean(sales_data)
# Медиана (среднее значение при сортировке по возрастанию)
median_sales = stats.median(sales_data)
# Мода (наиболее часто встречающееся значение)
# Для примера добавим повторяющиеся значения
extended_sales = sales_data + [1300, 1300, 1800]
mode_sales = stats.mode(extended_sales)
print(f"Среднее значение продаж: {mean_sales:.2f}")
print(f"Медианное значение продаж: {median_sales}")
print(f"Мода (наиболее частое значение): {mode_sales}")
Результат выполнения:
Среднее значение продаж: 1485.71
Медианное значение продаж: 1400
Мода (наиболее частое значение): 1300
Для более сложных данных модуль предлагает дополнительные варианты:
- stats.median_low() — выбирает меньшее из центральных значений (полезно для целочисленных данных)
- stats.median_high() — выбирает большее из центральных значений
- stats.multimode() — возвращает список всех мод (особенно полезно, если несколько значений встречаются с одинаковой частотой)
- stats.fmean() — быстрое вычисление среднего с приведением к типу float (доступно с Python 3.8)
- stats.geometric_mean() — геометрическое среднее (для Python 3.8 и выше)
- stats.harmonic_mean() — гармоническое среднее (полезно для усреднения отношений)
Пример использования расширенных функций среднего значения:
import statistics as stats
# Данные о времени выполнения операций (в секундах)
execution_times = [0\.12, 0.18, 0.15, 0.22, 0.10]
# Арифметическое среднее
arithmetic_mean = stats.mean(execution_times)
# Геометрическое среднее (подходит для усреднения темпов изменения)
geometric_mean = stats.geometric_mean(execution_times)
# Гармоническое среднее (хорошо для усреднения скоростей)
harmonic_mean = stats.harmonic_mean(execution_times)
print(f"Арифметическое среднее: {arithmetic_mean:.4f}")
print(f"Геометрическое среднее: {geometric_mean:.4f}")
print(f"Гармоническое среднее: {harmonic_mean:.4f}")
Результат:
Арифметическое среднее: 0.1540
Геометрическое среднее: 0.1481
Гармоническое среднее: 0.1425
Меры разброса
Для оценки вариативности данных модуль statistics
предлагает следующие функции:
import statistics as stats
# Измерения температуры за неделю
temperatures = [22\.5, 23.1, 21.8, 24.5, 22.7, 23.0, 22.3]
# Стандартное отклонение (по выборке)
std_dev = stats.stdev(temperatures)
# Дисперсия (по выборке)
variance = stats.variance(temperatures)
# Стандартное отклонение (по генеральной совокупности)
pop_std_dev = stats.pstdev(temperatures)
# Дисперсия (по генеральной совокупности)
pop_variance = stats.pvariance(temperatures)
print(f"Стандартное отклонение (выборка): {std_dev:.2f}")
print(f"Дисперсия (выборка): {variance:.2f}")
print(f"Стандартное отклонение (совокупность): {pop_std_dev:.2f}")
print(f"Дисперсия (совокупность): {pop_variance:.2f}")
Важно понимать разницу между выборочными методами (stdev
, variance
) и методами для генеральной совокупности (pstdev
, pvariance
). Первые используются, когда вы анализируете часть данных и делаете выводы о большей популяции, вторые — когда у вас есть все возможные данные.
Функции | Применение | Формула | Когда использовать |
---|---|---|---|
variance(), stdev() | Для выборки | Делит сумму квадратов отклонений на (n-1) | Когда данные представляют часть общей популяции |
pvariance(), pstdev() | Для совокупности | Делит сумму квадратов отклонений на n | Когда данные охватывают всю изучаемую совокупность |
quantiles() | Разделение на группы | Сортирует и делит данные на равные части | Для определения распределения данных |
correlation() | Связь между наборами данных | Корреляция Пирсона | Для измерения линейной зависимости |
Работа с выборками данных через модуль statistics
При анализе данных часто приходится иметь дело с выборками различного размера и структуры. Модуль statistics
предоставляет ряд инструментов, которые значительно упрощают работу с такими данными, особенно когда речь идет о неоднородных или группированных выборках. 🔍
Мария Соколова, data scientist
В 2023 году я работала над проектом по анализу медицинских данных для исследования эффективности нового препарата. Мы собирали информацию о реакции пациентов из 15 разных клиник, и результаты радикально отличались не только по эффекту, но и по количеству наблюдений.
Использование тяжелых библиотек аналитики для первичной обработки казалось неоправданным, но я нуждалась в надежном инструменте для работы с этими разнородными данными. Модуль
statistics
с его функциями для работы с весами и группировками стал для меня настоящим открытием.Особенно полезной оказалась функция
NormalDist
, которая позволила быстро оценить вероятность различных результатов для каждой клиники, не прибегая к сложным вычислениям и дополнительным зависимостям. Это сэкономило нам около 2 недель на предварительном анализе и позволило оперативно отобрать наиболее перспективные данные для глубокого изучения.
Работа с группированными данными
Модуль statistics
позволяет эффективно работать с данными, которые естественным образом разбиваются на группы или имеют различные веса. Например, расчет средневзвешенного значения:
import statistics as stats
# Оценки студентов и вес каждой оценки (в процентах)
grades = [85, 92, 78, 90, 88]
weights = [20, 30, 15, 20, 15] # % от итоговой оценки
# Пересчитываем проценты в доли
weights_fraction = [w/100 for w in weights]
# Вычисляем средневзвешенную оценку
weighted_avg = sum(g * w for g, w in zip(grades, weights_fraction))
print(f"Средневзвешенная оценка: {weighted_avg:.2f}")
# Для Python 3.8+ можно использовать встроенную функцию
if hasattr(stats, 'fmean'):
weighted_average = stats.fmean(grades, weights=weights)
print(f"Средневзвешенная (через fmean): {weighted_average:.2f}")
Для работы с частотными данными можно использовать подход с "распаковкой" значений:
import statistics as stats
# Частотные данные: значения и их частоты
values = [10, 20, 30, 40, 50]
frequencies = [5, 12, 8, 3, 2]
# Создаем "распакованный" список, повторяя каждое значение согласно его частоте
expanded_data = [val for val, freq in zip(values, frequencies) for _ in range(freq)]
# Теперь можем применять обычные статистические функции
median_value = stats.median(expanded_data)
mode_value = stats.mode(expanded_data)
print(f"Медианное значение: {median_value}")
print(f"Мода: {mode_value}")
Работа с нормальным распределением
С версии Python 3.8 в модуль statistics
добавлен класс NormalDist
, который упрощает работу с нормальным распределением:
import statistics as stats
from statistics import NormalDist
import math
# Данные о росте взрослых мужчин (см)
height_data = [178, 175, 182, 168, 185, 179, 173, 176, 180, 177]
# Создаем объект нормального распределения на основе данных
height_dist = NormalDist.from_samples(height_data)
# Получаем параметры распределения
mean_height = height_dist.mean
std_dev_height = height_dist.stdev
print(f"Среднее значение роста: {mean_height:.2f} см")
print(f"Стандартное отклонение: {std_dev_height:.2f} см")
# Вычисляем вероятность того, что случайно выбранный человек будет выше 185 см
prob_above_185 = 1 – height_dist.cdf(185)
print(f"Вероятность встретить человека выше 185 см: {prob_above_185:.2%}")
# Находим рост, выше которого находятся только 5% населения
height_95_percentile = height_dist.inv_cdf(0.95)
print(f"95-й процентиль роста: {height_95_percentile:.2f} см")
# Расчет доверительного интервала для среднего (95%)
n = len(height_data)
margin_of_error = 1.96 * (std_dev_height / math.sqrt(n))
ci_low = mean_height – margin_of_error
ci_high = mean_height + margin_of_error
print(f"95% доверительный интервал для среднего: "
f"[{ci_low:.2f}, {ci_high:.2f}] см")
NormalDist
предоставляет широкие возможности для расчетов, связанных с нормальным распределением:
cdf()
— функция кумулятивного распределения для расчета вероятностейinv_cdf()
— обратная функция для нахождения значений по процентилямoverlap()
— степень перекрытия двух нормальных распределенийpdf()
— функция плотности вероятностиsamples()
— генерация случайных значений из этого распределения
Работа с квантилями также стала доступнее с версии Python 3.8 благодаря функции quantiles()
:
import statistics as stats
# Данные о времени выполнения запросов к базе данных (мс)
response_times = [45, 37, 42, 50, 27, 38, 33, 55, 42, 61, 59, 55, 44, 38]
# Разделим данные на квартили (4 равные группы)
quartiles = stats.quantiles(response_times, n=4)
print(f"Квартили времени ответа: {quartiles}")
# Разделим данные на децили (10 равных групп)
deciles = stats.quantiles(response_times, n=10)
print(f"Децили времени ответа: {deciles}")
# Определим межквартильный размах (IQR)
iqr = quartiles[2] – quartiles[0]
print(f"Межквартильный размах: {iqr} мс")
# Идентификация выбросов по правилу 1.5*IQR
lower_fence = quartiles[0] – 1.5 * iqr
upper_fence = quartiles[2] + 1.5 * iqr
outliers = [x for x in response_times if x < lower_fence or x > upper_fence]
print(f"Границы для выбросов: [{lower_fence:.2f}, {upper_fence:.2f}]")
print(f"Выбросы в данных: {outliers}")
Визуализация результатов статистических вычислений
Визуализация статистических результатов — ключевой шаг в анализе данных, который превращает абстрактные числа в наглядную информацию. Хотя модуль statistics
сам по себе не предоставляет инструментов для построения графиков, существуют отличные способы интеграции его результатов с популярными библиотеками визуализации. 📈
Рассмотрим, как можно визуализировать результаты вычислений, полученных с помощью модуля statistics
, используя matplotlib
и seaborn
.
import statistics as stats
import matplotlib.pyplot as plt
import numpy as np
# Генерация тестовых данных о продажах
monthly_sales = [12500, 11800, 13200, 14100, 15800, 16500,
16200, 17000, 18200, 19500, 19800, 21000]
# Расчет статистических показателей
mean_sales = stats.mean(monthly_sales)
median_sales = stats.median(monthly_sales)
std_dev = stats.stdev(monthly_sales)
# Создание базового графика
plt.figure(figsize=(10, 6))
# Построение динамики продаж
months = list(range(1, 13))
plt.plot(months, monthly_sales, marker='o', linestyle='-',
color='blue', label='Ежемесячные продажи')
# Добавление среднего и доверительного интервала
plt.axhline(y=mean_sales, color='r', linestyle='--',
label=f'Среднее: {mean_sales:.2f}')
plt.axhline(y=median_sales, color='g', linestyle=':',
label=f'Медиана: {median_sales:.2f}')
# Создание области доверительного интервала (±1 стандартное отклонение)
plt.fill_between(months, mean_sales – std_dev, mean_sales + std_dev,
color='red', alpha=0.2,
label=f'±1 станд. откл. ({std_dev:.2f})')
# Оформление графика
plt.title('Динамика продаж за год с статистическими показателями')
plt.xlabel('Месяц')
plt.ylabel('Объем продаж (₽)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(months)
plt.tight_layout()
plt.show()
Для более сложной визуализации распределения данных можно использовать гистограммы и теоретические распределения:
import statistics as stats
from statistics import NormalDist
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
# Набор данных о времени выполнения задачи (в секундах)
task_times = [5\.2, 4.8, 6.1, 5.5, 5.3, 4.9, 5.6, 6.2, 5.0, 5.4,
4.7, 5.8, 5.2, 5.1, 6.0, 4.6, 5.7, 5.3, 5.9, 5.4]
# Рассчитываем статистики
mean_time = stats.mean(task_times)
std_dev = stats.stdev(task_times)
median_time = stats.median(task_times)
# Создаем объект нормального распределения
normal_dist = NormalDist(mu=mean_time, sigma=std_dev)
# Создаем график
plt.figure(figsize=(12, 7))
# Основной график: гистограмма с кривой плотности
sns.histplot(task_times, kde=True, stat="density",
color="skyblue", label="Фактические данные")
# Добавляем теоретическую кривую нормального распределения
x = np.linspace(min(task_times) – 1, max(task_times) + 1, 1000)
y = [normal_dist.pdf(value) for value in x]
plt.plot(x, y, 'r--', linewidth=2,
label=f'Норм. распр. (μ={mean_time:.2f}, σ={std_dev:.2f})')
# Отмечаем среднее и медиану
plt.axvline(x=mean_time, color='red', linestyle='-', linewidth=1.5,
label=f'Среднее: {mean_time:.2f}')
plt.axvline(x=median_time, color='green', linestyle=':', linewidth=1.5,
label=f'Медиана: {median_time:.2f}')
# Добавляем квантили (25-й и 75-й процентили)
q1, q3 = stats.quantiles(task_times, n=4)[0], stats.quantiles(task_times, n=4)[2]
plt.axvline(x=q1, color='purple', linestyle='-.', alpha=0.7,
label=f'Q1: {q1:.2f}')
plt.axvline(x=q3, color='purple', linestyle='-.', alpha=0.7,
label=f'Q3: {q3:.2f}')
# Оформление графика
plt.title('Распределение времени выполнения задачи')
plt.xlabel('Время (секунды)')
plt.ylabel('Плотность')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Для сравнения нескольких наборов данных можно использовать диаграмму размаха (box plot) и диаграмму скрипки (violin plot):
import statistics as stats
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
# Данные о производительности трех разных алгоритмов
algorithm_A = [32, 35, 29, 37, 33, 31, 35, 34, 30, 36]
algorithm_B = [42, 39, 36, 40, 44, 38, 45, 37, 41, 43]
algorithm_C = [28, 35, 22, 41, 33, 27, 42, 30, 38, 25]
# Создаем DataFrame для удобной работы
data = {
'Алгоритм A': algorithm_A,
'Алгоритм B': algorithm_B,
'Алгоритм C': algorithm_C
}
df = pd.DataFrame(data)
# Расчет основных статистик для каждого алгоритма
stats_data = []
for algo_name, values in data.items():
stats_data.append({
'Алгоритм': algo_name,
'Среднее': stats.mean(values),
'Медиана': stats.median(values),
'Станд. откл.': stats.stdev(values),
'CV (%)': (stats.stdev(values) / stats.mean(values)) * 100
})
stats_df = pd.DataFrame(stats_data)
# Создаем визуализацию
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# Box plot на первом графике
sns.boxplot(data=df, ax=ax1)
ax1.set_title('Сравнение производительности алгоритмов (box plot)')
ax1.set_ylabel('Время выполнения (мс)')
ax1.grid(True, alpha=0.3)
# Violin plot на втором графике
sns.violinplot(data=df, ax=ax2)
ax2.set_title('Сравнение распределений производительности (violin plot)')
ax2.set_ylabel('Время выполнения (мс)')
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Вывод статистической сводки
print("Статистическая сводка по алгоритмам:")
print(stats_df.to_string(index=False, float_format=lambda x: f"{x:.2f}"))
Визуализация корреляции между наборами данных (доступно с Python 3.10):
import statistics as stats
import matplotlib.pyplot as plt
import numpy as np
# Проверяем доступность функции корреляции (Python 3.10+)
if hasattr(stats, 'correlation'):
# Генерируем связанные данные
np.random.seed(42)
x = np.random.normal(0, 1, 100)
# Три набора данных с разной степенью корреляции с x
y1 = x * 0.8 + np.random.normal(0, 0.3, 100) # сильная положительная
y2 = x * -0.5 + np.random.normal(0, 0.5, 100) # средняя отрицательная
y3 = np.random.normal(0, 1, 100) # почти нет корреляции
# Расчет корреляции
corr1 = stats.correlation(x, y1)
corr2 = stats.correlation(x, y2)
corr3 = stats.correlation(x, y3)
# Визуализация
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15, 5))
# Первый график
ax1.scatter(x, y1, alpha=0.7)
ax1.set_title(f'Сильная положит. корреляция: {corr1:.2f}')
ax1.set_xlabel('x')
ax1.set_ylabel('y1')
ax1.grid(True, alpha=0.3)
# Второй график
ax2.scatter(x, y2, alpha=0.7, color='green')
ax2.set_title(f'Средняя отрицат. корреляция: {corr2:.2f}')
ax2.set_xlabel('x')
ax2.set_ylabel('y2')
ax2.grid(True, alpha=0.3)
# Третий график
ax3.scatter(x, y3, alpha=0.7, color='red')
ax3.set_title(f'Нет корреляции: {corr3:.2f}')
ax3.set_xlabel('x')
ax3.set_ylabel('y3')
ax3.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
else:
print("Функция correlation() доступна только в Python 3.10+")
Определить свои сильные стороны в анализе данных и статистике поможет Тест на профориентацию от Skypro. Пройдите быстрое тестирование и узнайте, подходит ли вам карьера в области обработки данных с использованием Python и его статистических инструментов. Тест оценит ваши аналитические способности, логическое мышление и математические навыки — ключевые компетенции для успешной работы с data science и статистическими функциями. Результаты включают персональные рекомендации по развитию в 2025 году!
Практические решения аналитических задач с модулем statistics
Модуль statistics
позволяет эффективно решать реальные аналитические задачи без необходимости обращаться к более сложным библиотекам. Рассмотрим несколько практических примеров, демонстрирующих мощь этого компактного инструмента. 🛠️
Сравнение результатов A/B-тестирования
Допустим, мы провели тестирование двух версий веб-страницы и хотим определить, есть ли статистически значимое различие в конверсии:
import statistics as stats
import math
from statistics import NormalDist
# Результаты A/B-теста
# Версия A: 120 конверсий из 1500 посетителей
# Версия B: 150 конверсий из 1600 посетителей
def analyze_ab_test(conversions_a, visitors_a, conversions_b, visitors_b,
confidence=0.95):
# Рассчитываем коэффициенты конверсии
conv_rate_a = conversions_a / visitors_a
conv_rate_b = conversions_b / visitors_b
# Стандартная ошибка для каждой конверсии
se_a = math.sqrt(conv_rate_a * (1 – conv_rate_a) / visitors_a)
se_b = math.sqrt(conv_rate_b * (1 – conv_rate_b) / visitors_b)
# Стандартная ошибка разницы между конверсиями
se_diff = math.sqrt(se_a**2 + se_b**2)
# Разница в конверсии
conv_diff = conv_rate_b – conv_rate_a
# Z-статистика
z_score = conv_diff / se_diff
# P-значение (двустороннее)
p_value = 2 * (1 – NormalDist().cdf(abs(z_score)))
# Относительное изменение конверсии
rel_change = (conv_rate_b – conv_rate_a) / conv_rate_a * 100
# Доверительный интервал
z_critical = NormalDist().inv_cdf((1 + confidence) / 2)
margin_of_error = z_critical * se_diff
ci_lower = conv_diff – margin_of_error
ci_upper = conv_diff + margin_of_error
# Результаты
results = {
"conversion_a": conv_rate_a,
"conversion_b": conv_rate_b,
"absolute_diff": conv_diff,
"relative_change": rel_change,
"p_value": p_value,
"confidence_interval": (ci_lower, ci_upper),
"statistically_significant": p_value < (1 – confidence)
}
return results
# Анализируем тест
results = analyze_ab_test(120, 1500, 150, 1600)
# Выводим результаты
print(f"Конверсия A: {results['conversion_a']:.2%}")
print(f"Конверсия B: {results['conversion_b']:.2%}")
print(f"Абсолютная разница: {results['absolute_diff']:.2%}")
print(f"Относительное изменение: {results['relative_change']:.2f}%")
print(f"P-значение: {results['p_value']:.4f}")
print(f"95% доверительный интервал: "
f"({results['confidence_interval'][0]:.2%}, "
f"{results['confidence_interval'][1]:.2%})")
print(f"Статистическая значимость: {'Да' if results['statistically_significant'] else 'Нет'}")
Анализ выбросов в данных
Выявление и обработка выбросов — критическая задача при подготовке данных к анализу:
import statistics as stats
def detect_outliers(data, method="iqr", threshold=1.5):
"""
Обнаруживает выбросы в наборе данных.
Методы:
- 'iqr': межквартильный размах (по умолчанию)
- 'zscore': стандартное отклонение
"""
if method == "iqr":
# Метод межквартильного размаха
q1, q3 = stats.quantiles(sorted(data), n=4)[0], stats.quantiles(sorted(data), n=4)[2]
iqr = q3 – q1
lower_bound = q1 – threshold * iqr
upper_bound = q3 + threshold * iqr
elif method == "zscore":
# Метод Z-оценки
mean = stats.mean(data)
stdev = stats.stdev(data)
lower_bound = mean – threshold * stdev
upper_bound = mean + threshold * stdev
else:
raise ValueError("Неизвестный метод обнаружения выбросов")
# Находим выбросы
outliers = [x for x in data if x < lower_bound or x > upper_bound]
outliers_indices = [i for i, x in enumerate(data) if x < lower_bound or x > upper_bound]
return {
"bounds": (lower_bound, upper_bound),
"outliers": outliers,
"outliers_indices": outliers_indices,
"cleaned_data": [x for x in data if lower_bound <= x <= upper_bound]
}
# Тестовые данные с выбросами
salaries = [65000, 67000, 72000, 59000, 78000, 62000,
69000, 195000, 58000, 74000, 61000, 71000]
# Анализируем данные на выбросы методом IQR
outliers_iqr = detect_outliers(salaries, method="iqr")
# Анализируем данные на выбросы методом Z-score
outliers_zscore = detect_outliers(salaries, method="zscore", threshold=2)
# Выводим результаты
print("Анализ выбросов методом межквартильного размаха (IQR):")
print(f"Границы: {outliers_iqr['bounds']}")
print(f"Выбросы: {outliers_iqr['outliers']}")
print(f"Индексы выбросов: {outliers_iqr['outliers_indices']}")
print(f"Средняя зарплата с выбросами: {stats.mean(salaries):.2f}")
print(f"Средняя зарплата без выбросов: {stats.mean(outliers_iqr['cleaned_data']):.2f}")
print("\nАнализ выбросов методом Z-score (порог = 2):")
print(f"Границы: {outliers_zscore['bounds']}")
print(f"Выбросы: {outliers_zscore['outliers']}")
print(f"Индексы выбросов: {outliers_zscore['outliers_indices']}")
print(f"Средняя зарплата без выбросов: {stats.mean(outliers_zscore['cleaned_data']):.2f}")
Оценка эффективности инвестиций
Использование статистических методов для оценки эффективности и риска инвестиционного портфеля:
import statistics as stats
import math
from datetime import datetime, timedelta
import random
# Симулируем историческую доходность различных активов за последние 12 месяцев
def generate_returns(mean, stdev, periods=12):
"""Генерирует случайные месячные доходности с заданными параметрами"""
random.seed(42) # для воспроизводимости результатов
return [random.normalvariate(mean/12, stdev/math.sqrt(12)) for _ in range(periods)]
# Акции
stock_returns = generate_returns(0.10, 0.20) # Ожидаемая годовая доходность 10%, волатильность 20%
# Облигации
bond_returns = generate_returns(0.04, 0.05) # Ожидаемая годовая доходность 4%, волатильность 5%
# Золото
gold_returns = generate_returns(0.06, 0.15) # Ожидаемая годовая доходность 6%, волатильность 15%
# Создаем портфель с разными весами
portfolio_weights = {
"Акции": 0.6,
"Облигации": 0.3,
"Золото": 0.1
}
# Объединяем данные
assets_returns = {
"Акции": stock_returns,
"Облигации": bond_returns,
"Золото": gold_returns
}
# Анализируем каждый актив
asset_analysis = {}
for asset_name, returns in assets_returns.items():
monthly_mean = stats.mean(returns)
monthly_stdev = stats.stdev(returns)
annual_return = (1 + monthly_mean)**12 – 1
annual_volatility = monthly_stdev * math.sqrt(12)
sharpe_ratio = annual_return / annual_volatility if annual_volatility != 0 else 0
asset_analysis[asset_name] = {
"monthly_mean": monthly_mean,
"monthly_stdev": monthly_stdev,
"annual_return": annual_return,
"annual_volatility": annual_volatility,
"sharpe_ratio": sharpe_ratio,
"min_return": min(returns),
"max_return": max(returns)
}
# Рассчитываем доходность портфеля за каждый месяц
portfolio_returns = []
for month in range(12):
month_return = sum(assets_returns[asset][month] * weight
for asset, weight in portfolio_weights.items())
portfolio_returns.append(month_return)
# Анализируем портфель
portfolio_monthly_mean = stats.mean(portfolio_returns)
portfolio_monthly_stdev = stats.stdev(portfolio_returns)
portfolio_annual_return = (1 + portfolio_monthly_mean)**12 – 1
portfolio_annual_volatility = portfolio_monthly_stdev * math.sqrt(12)
portfolio_sharpe_ratio = portfolio_annual_return / portfolio_annual_volatility
# Выводим результаты
print("Анализ эффективности инвестиционного портфеля\n")
print("Характеристики отдельных активов:")
for asset, analysis in asset_analysis.items():
print(f"\n{asset}:")
print(f" Годовая доходность: {analysis['annual_return']:.2%}")
print(f" Годовая волатильность: {analysis['annual_volatility']:.2%}")
print(f" Коэффициент Шарпа: {analysis['sharpe_ratio']:.2f}")
print(f" Минимальная месячная доходность: {analysis['min_return']:.2%}")
print(f" Максимальная месячная доходность: {analysis['max_return']:.2%}")
print("\nАнализ всего портфеля:")
print(f"Состав портфеля: {portfolio_weights}")
print(f"Ожидаемая годовая доходность: {portfolio_annual_return:.2%}")
print(f"Ожидаемая годовая волатильность: {portfolio_annual_volatility:.2%}")
print(f"Коэффициент Шарпа портфеля: {portfolio_sharpe_ratio:.2f}")
print(f"Минимальная месячная доходность: {min(portfolio_returns):.2%}")
print(f"Максимальная месячная доходность: {max(portfolio_returns):.2%}")
# Корреляционный анализ (для Python 3.10+)
if hasattr(stats, 'correlation'):
print("\nКорреляционная матрица:")
assets = list(assets_returns.keys())
for i, asset1 in enumerate(assets):
correlations = []
for asset2 in assets:
corr = stats.correlation(assets_returns[asset1], assets_returns[asset2])
correlations.append(f"{corr:.2f}")
print(f"{asset1}: [{', '.join(correlations)}]")
Модуль
statistics
— это настоящая находка для Python-разработчиков всех уровней. Он представляет собой мост между базовыми математическими операциями и специализированными библиотеками для анализа данных. Благодаря своей доступности, низкому порогу вхождения и встроенной природе, он становится идеальным инструментом для первичного статистического анализа, прототипирования решений и ситуаций, где избыточная функциональность тяжеловесных библиотек нежелательна. Используя примеры из этой статьи, вы сможете превратить модульstatistics
из малоизвестного компонента стандартной библиотеки в рабочую лошадку вашего статистического инструментария.