ЛР 2. Численные вычисления и анализ данных с NumPy¶
Тема: Численные вычисления, матричные операции, статистический анализ и визуализация данных с использованием библиотеки NumPy
Цель работы¶
- Освоить основы работы с массивами и матрицами в NumPy.
- Научиться выполнять векторные и матричные операции (сложение, умножение, определитель, обратная матрица, решение СЛАУ).
- Изучить инструменты статистического анализа: среднее, медиана, стандартное отклонение, перцентили.
- Реализовать Min-Max нормализацию данных.
- Построить визуализации (гистограмма, тепловая карта, линейный график) с помощью Matplotlib и Seaborn.
- Обеспечить соответствие кода стандартам DATS: тесты, аннотации типов (PEP 484), документация (PEP 257), стиль (PEP 8).
Задание¶
- Реализовать функции создания и преобразования массивов (
create_vector,create_matrix,reshape_vector,transpose_matrix). - Реализовать векторные операции (
vector_add,scalar_multiply,elementwise_multiply,dot_product). - Реализовать матричные операции (
matrix_multiply,matrix_determinant,matrix_inverse,solve_linear_system). - Реализовать статистический анализ (
load_dataset,statistical_analysis,normalize_data). - Реализовать визуализацию данных (
plot_histogram,plot_heatmap,plot_line). - Все функции должны проходить предоставленные тесты (17 тестов), содержать аннотации типов и документацию.
Код¶
Исходный код: github.com/qulin-ds/pythonf/tree/main/lab_12
Создание и обработка массивов¶
def create_vector() -> np.ndarray:
"""Создать одномерный массив целых чисел от 0 до 9."""
return np.arange(10)
def create_matrix() -> np.ndarray:
"""Создать матрицу 5x5 со случайными числами из [0, 1)."""
return np.random.rand(5, 5)
def reshape_vector(vec: np.ndarray) -> np.ndarray:
"""Преобразовать одномерный массив формы (10,) в матрицу (2, 5)."""
return vec.reshape(2, 5)
def transpose_matrix(mat: np.ndarray) -> np.ndarray:
"""Транспонировать матрицу."""
return mat.T
Нюансы:
np.arange(10)создаёт массив типаint64— это важно для дальнейших операций, где типы могут неявно меняться.np.random.randгенерирует числа из равномерного распределения на полуинтервале[0, 1).reshapeне копирует данные — возвращает view на тот же буфер памяти. Изменение элемента в результате изменит оригинал.
Векторные операции¶
def vector_add(a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Выполнить поэлементное сложение двух векторов."""
return a + b
def scalar_multiply(vec: np.ndarray, scalar: Union[int, float]) -> np.ndarray:
"""Умножить вектор на скаляр."""
return vec * scalar
def elementwise_multiply(a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Выполнить поэлементное умножение двух массивов."""
return a * b
def dot_product(a: np.ndarray, b: np.ndarray) -> float:
"""Вычислить скалярное произведение двух векторов."""
return np.dot(a, b)
Нюансы:
- Оператор
*дляndarrayвыполняет поэлементное умножение (Hadamard product), а не матричное. np.dotдля одномерных массивов вычисляет скалярное произведение, но для двумерных — матричное умножение. Для ясности при работе с матрицами лучше использовать оператор@.- Broadcasting: если формы массивов не совпадают, NumPy автоматически «расширяет» размерности. Для скалярного умножения скаляр broadcast'ится до формы вектора.
Матричные операции¶
def matrix_multiply(a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Выполнить матричное умножение двух матриц."""
return a @ b
def matrix_determinant(a: np.ndarray) -> float:
"""Вычислить определитель квадратной матрицы."""
return np.linalg.det(a)
def matrix_inverse(a: np.ndarray) -> np.ndarray:
"""Вычислить обратную матрицу."""
return np.linalg.inv(a)
def solve_linear_system(a: np.ndarray, b: np.ndarray) -> np.ndarray:
"""Решить систему линейных уравнений Ax = b."""
return np.linalg.solve(a, b)
Нюансы:
- Оператор
@(PEP 465) — рекомендуемый способ матричного умножения в Python 3.5+. np.linalg.detиспользует LU-разложение; для больших матриц возможна потеря точности из-за чисел с плавающей запятой.np.linalg.invброситLinAlgError, если матрица вырождена (определитель ≈ 0).np.linalg.solveчисленно устойчивее, чем вычислениеinv(A) @ b, так как не требует явного нахождения обратной матрицы.
Статистический анализ¶
def load_dataset(path: str = "data/students_scores.csv") -> np.ndarray:
"""Загрузить CSV-файл и вернуть данные как NumPy-массив."""
return pd.read_csv(path).to_numpy()
def statistical_analysis(data: np.ndarray) -> Dict[str, float]:
"""Вычислить основные статистические показатели массива."""
return {
"mean": np.mean(data),
"median": np.median(data),
"std": np.std(data),
"min": np.min(data),
"max": np.max(data),
"percentile_25": np.percentile(data, 25),
"percentile_75": np.percentile(data, 75),
}
def normalize_data(data: np.ndarray) -> np.ndarray:
"""Выполнить Min-Max нормализацию массива в диапазон [0, 1]."""
data_min = np.min(data)
data_max = np.max(data)
return (data - data_min) / (data_max - data_min)
Нюансы:
pd.read_csv().to_numpy()— удобный способ получить массив из CSV, но теряется информация о заголовках столбцов.np.stdпо умолчанию используетddof=0(смещённая оценка). Для несмещённой оценки следует передатьddof=1.- При нормализации необходимо учитывать случай
max == min— деление на ноль. В данной реализации предполагается, что данные содержат хотя бы два различных значения.
Визуализация¶
def plot_histogram(data: np.ndarray) -> None:
"""Построить и сохранить гистограмму распределения оценок."""
os.makedirs("plots", exist_ok=True)
plt.figure()
plt.hist(data, bins=10, edgecolor="black", alpha=0.7)
plt.title("Распределение оценок по математике")
plt.xlabel("Оценка")
plt.ylabel("Частота")
plt.savefig("plots/histogram.png", dpi=150, bbox_inches="tight")
plt.close()
def plot_heatmap(matrix: np.ndarray) -> None:
"""Построить и сохранить тепловую карту корреляции."""
os.makedirs("plots", exist_ok=True)
plt.figure()
sns.heatmap(matrix, annot=True, cmap="coolwarm", fmt=".2f")
plt.title("Корреляционная матрица предметов")
plt.savefig("plots/heatmap.png", dpi=150, bbox_inches="tight")
plt.close()
def plot_line(x: np.ndarray, y: np.ndarray) -> None:
"""Построить и сохранить линейный график оценок студентов."""
os.makedirs("plots", exist_ok=True)
plt.figure()
plt.plot(x, y, marker="o", linestyle="-", color="steelblue")
plt.title("Оценки студентов по математике")
plt.xlabel("Номер студента")
plt.ylabel("Оценка")
plt.grid(True, alpha=0.3)
plt.savefig("plots/line_plot.png", dpi=150, bbox_inches="tight")
plt.close()
Нюансы:
matplotlib.use("Agg")устанавливается в начале модуля для работы без графического интерфейса (важно для серверов и CI).plt.close()обязателен послеsavefig, иначе фигуры накапливаются в памяти.bbox_inches="tight"автоматически обрезает пустые поля вокруг графика.
Тестирование¶
Все 17 тестов проходят успешно:
test.py::test_create_vector PASSED
test.py::test_create_matrix PASSED
test.py::test_reshape_vector PASSED
test.py::test_vector_add PASSED
test.py::test_scalar_multiply PASSED
test.py::test_elementwise_multiply PASSED
test.py::test_dot_product PASSED
test.py::test_matrix_multiply PASSED
test.py::test_matrix_determinant PASSED
test.py::test_matrix_inverse PASSED
test.py::test_solve_linear_system PASSED
test.py::test_load_dataset PASSED
test.py::test_statistical_analysis PASSED
test.py::test_normalization PASSED
test.py::test_plot_histogram PASSED
test.py::test_plot_heatmap PASSED
test.py::test_plot_line PASSED
============================= 17 passed =============================
Соответствие DATS¶
| Критерий | Стандарт | Статус |
|---|---|---|
| Тесты | pytest | 17/17 passed |
| Аннотации типов | PEP 484 | Все функции аннотированы (-> np.ndarray, -> float, -> Dict[str, float], -> None) |
| Документация | PEP 257 | Все функции содержат docstring с описанием, Args и Returns |
| Стиль кода | PEP 8 | Соблюдён (проверено линтером) |
Выводы¶
В ходе выполнения лабораторной работы были получены следующие навыки:
- Работа с массивами NumPy — создание, изменение формы, транспонирование. Понимание разницы между
viewиcopy. - Векторные операции — поэлементные операции, broadcasting, скалярное произведение.
- Матричные операции — умножение (
@), определитель, обратная матрица, решение СЛАУ. Понимание численной устойчивостиlinalg.solvevsinv. - Статистический анализ — вычисление описательных статистик, Min-Max нормализация. Осознание особенностей
ddofвnp.std. - Визуализация — построение графиков с Matplotlib и Seaborn, сохранение в файлы с настройкой DPI и backend.
- Качество кода — соблюдение стандартов DATS: тесты, аннотации типов, документация, PEP 8.