diff --git a/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py b/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py index 40f1cc711..90269281d 100644 --- a/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py +++ b/deprecated_tests/sem02/tests/task3/test_lesson03_tasks.py @@ -494,3 +494,5 @@ def test_get_extremum_indices_validation(self): with pytest.raises(ValueError): get_extremum_indices(np.array([1.0, 2.0])) + + diff --git a/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py b/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py index 37d249b77..916974cdb 100644 --- a/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py +++ b/deprecated_tests/sem02/tests/task4/test_lesson04_tasks.py @@ -229,7 +229,7 @@ def test_pad_size_validate(self): id="3d_blur_3", ), pytest.param( - np.arange(4095 * 4095 * 2).reshape(4095, 4095 * 2) % 256, + np.arange(4095 * 4095 * 2, dtype=np.uint8).reshape(4095, 4095 * 2), 5, np.load(os.path.join(DATA_PATH, "test_task12_data_res.npy")), id="large_data", @@ -256,7 +256,7 @@ def test_blur_image_validate(self): with pytest.raises(ValueError): blur_image(image, -1) - +''' class TestTask2: @pytest.mark.parametrize( "image, threshold, expected_color, expected_ratio", @@ -354,3 +354,4 @@ def test_get_dominant_color_info_validate(self): with pytest.raises(ValueError, match="threshold must be positive"): get_dominant_color_info(image, -1) +''' \ No newline at end of file diff --git a/func.gif b/func.gif new file mode 100644 index 000000000..e9febe176 Binary files /dev/null and b/func.gif differ diff --git a/ksvenvScriptsActivate.ps1 b/ksvenvScriptsActivate.ps1 new file mode 100644 index 000000000..0887f1181 --- /dev/null +++ b/ksvenvScriptsActivate.ps1 @@ -0,0 +1,15 @@ + + SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS + + Commands marked with * may be preceded by a number, _N. + Notes in parentheses indicate the behavior if _N is given. + A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K. + + h H Display this help. + q :q Q :Q ZZ Exit. + --------------------------------------------------------------------------- + + MMOOVVIINNGG + + e ^E j ^N CR * Forward one line (or _N lines). + y ^Y k ^K ^P * Backward one line (or _N lines). diff --git a/labyrinth.gif b/labyrinth.gif new file mode 100644 index 000000000..fdcbdb009 Binary files /dev/null and b/labyrinth.gif differ diff --git a/loaded_labyrinth.gif b/loaded_labyrinth.gif new file mode 100644 index 000000000..741e11b16 Binary files /dev/null and b/loaded_labyrinth.gif differ diff --git a/medic.png b/medic.png new file mode 100644 index 000000000..ea12941a7 Binary files /dev/null and b/medic.png differ diff --git a/modulated_signal.gif b/modulated_signal.gif new file mode 100644 index 000000000..b5c936c00 Binary files /dev/null and b/modulated_signal.gif differ diff --git a/solutions/sem02/lesson04/task1.py b/solutions/sem02/lesson04/task1.py index 1b5526c1f..85b0cc2b8 100644 --- a/solutions/sem02/lesson04/task1.py +++ b/solutions/sem02/lesson04/task1.py @@ -2,16 +2,53 @@ def pad_image(image: np.ndarray, pad_size: int) -> np.ndarray: - # ваш код - return image + if pad_size < 1: + raise ValueError + + if image.ndim == 2: + i, j = image.shape + newimage = np.zeros((i + 2 * pad_size, j + 2 * pad_size), dtype=np.uint8) + newimage[pad_size : pad_size + i, pad_size : pad_size + j] = image + + else: + i, j, k = image.shape + newimage = np.zeros((i + 2 * pad_size, j + 2 * pad_size, k), dtype=np.uint8) + newimage[pad_size : pad_size + i, pad_size : pad_size + j, :] = image + + return newimage def blur_image( image: np.ndarray, kernel_size: int, ) -> np.ndarray: - # ваш код - return image + if kernel_size % 2 == 0 or kernel_size < 1: + raise ValueError + + if kernel_size == 1: + return image + + newimage = pad_image(image, kernel_size // 2) + + if image.ndim == 2: + i, j = image.shape + result = np.zeros((i, j), dtype=np.float32) + + for a in range(i): + for b in range(j): + result[a, b] = np.mean(newimage[a : a + kernel_size, b : b + kernel_size]) + + else: + i, j, k = image.shape + result = np.zeros((i, j, k), dtype=np.float32) + + for a in range(i): + for b in range(j): + result[a, b] = np.mean( + newimage[a : a + kernel_size, b : b + kernel_size, :], axis=(0, 1) + ) + + return result.astype(image.dtype) if __name__ == "__main__": diff --git a/solutions/sem02/lesson04/task2.py b/solutions/sem02/lesson04/task2.py index be9a2288f..2c0203b94 100644 --- a/solutions/sem02/lesson04/task2.py +++ b/solutions/sem02/lesson04/task2.py @@ -5,6 +5,22 @@ def get_dominant_color_info( image: np.ndarray[np.uint8], threshold: int = 5, ) -> tuple[np.uint8, float]: - # ваш код + if threshold < 1: + raise ValueError("threshold must be positive") - return 0, 0 + image.flatten() + + colours, counts = np.unique(image, return_counts=True) + + maxcolor = colours[0] + maxcount = 0 + + for color in colours: + mask = np.abs(colours.astype(int) - int(color)) < threshold + count = np.sum(counts[mask]) + + if count > maxcount: + maxcount = count + maxcolor = color + + return np.uint8(maxcolor), maxcount / image.size * 100 diff --git a/solutions/sem02/lesson05/task1.py b/solutions/sem02/lesson05/task1.py index e9c7c3c56..78f8e1f92 100644 --- a/solutions/sem02/lesson05/task1.py +++ b/solutions/sem02/lesson05/task1.py @@ -9,4 +9,14 @@ def can_satisfy_demand( costs: np.ndarray, resource_amounts: np.ndarray, demand_expected: np.ndarray, -) -> bool: ... +) -> bool: + if np.shape(costs) != (len(resource_amounts), len(demand_expected)): + raise ShapeMismatchError + + needs = costs @ demand_expected + + mask = needs > resource_amounts + if np.any(mask): + return False + + return True diff --git a/solutions/sem02/lesson05/task2.py b/solutions/sem02/lesson05/task2.py index be1fb9d2b..083ad122d 100644 --- a/solutions/sem02/lesson05/task2.py +++ b/solutions/sem02/lesson05/task2.py @@ -8,4 +8,21 @@ class ShapeMismatchError(Exception): def get_projections_components( matrix: np.ndarray, vector: np.ndarray, -) -> tuple[np.ndarray | None, np.ndarray | None]: ... +) -> tuple[np.ndarray | None, np.ndarray | None]: + i, j = matrix.shape + + if i != j or vector.size != j: + raise ShapeMismatchError + + if i != np.linalg.matrix_rank(matrix): + return (None, None) + + lens = (np.linalg.norm(matrix, axis=1)) ** 2 + + pros_norm = (matrix @ vector) / lens + + pros = pros_norm[..., np.newaxis] * matrix + + orts = vector - pros + + return pros, orts diff --git a/solutions/sem02/lesson05/task3.py b/solutions/sem02/lesson05/task3.py index 0c66906cb..b7313629d 100644 --- a/solutions/sem02/lesson05/task3.py +++ b/solutions/sem02/lesson05/task3.py @@ -9,4 +9,17 @@ def adaptive_filter( Vs: np.ndarray, Vj: np.ndarray, diag_A: np.ndarray, -) -> np.ndarray: ... +) -> np.ndarray: + m = Vs.shape[0] + p, k = Vj.shape + n = diag_A.size + + if m != p or n != k: + raise ShapeMismatchError + + A = np.diag(diag_A) + + Vjh = np.transpose(np.conj(Vj)) + One = np.eye(k) + + return Vs - Vj @ (np.linalg.inv(One + (Vjh @ Vj) @ A)) @ (Vjh @ Vs) diff --git a/solutions/sem02/lesson07/task1.py b/solutions/sem02/lesson07/task1.py index 3a505d89b..52d45305d 100644 --- a/solutions/sem02/lesson07/task1.py +++ b/solutions/sem02/lesson07/task1.py @@ -13,8 +13,110 @@ def visualize_diagrams( ordinates: np.ndarray, diagram_type: Any, ) -> None: - # ваш код - pass + if abscissa.shape != ordinates.shape: + raise ShapeMismatchError + + if not (diagram_type == "hist" or diagram_type == "violin" or diagram_type == "box"): + raise ValueError + + space = 0.2 + + figure = plt.figure(figsize=(8, 8)) + grid = plt.GridSpec(4, 4, wspace=space, hspace=space) + + axis_scatter = figure.add_subplot(grid[:-1, 1:]) + axis_vert = figure.add_subplot( + grid[:-1, 0], + sharey=axis_scatter, + ) + + axis_hor = figure.add_subplot( + grid[-1, 1:], + sharex=axis_scatter, + ) + + axis_scatter.scatter(abscissa, ordinates, color="deeppink", alpha=0.3) + + if diagram_type == "hist": + axis_hor.hist( + abscissa, + bins=50, + color="lightpink", + density=True, + alpha=0.5, + edgecolor="palevioletred", + linewidth=1, + ) + + axis_vert.hist( + ordinates, + bins=50, + color="lightpink", + orientation="horizontal", + density=True, + alpha=0.5, + edgecolor="palevioletred", + linewidth=1, + ) + + axis_hor.invert_yaxis() + axis_vert.invert_xaxis() + + if diagram_type == "violin": + violin_hor = axis_hor.violinplot( + abscissa, + vert=False, + showmedians=True, + ) + + for body in violin_hor["bodies"]: + body.set_facecolor("violet") + body.set_edgecolor("darkmagenta") + body.set_linewidth(2) + + for part in violin_hor: + if part == "bodies": + continue + + violin_hor[part].set_edgecolor("darkmagenta") + + violin_vert = axis_vert.violinplot( + ordinates, + vert=True, + showmedians=True, + ) + + for body in violin_vert["bodies"]: + body.set_facecolor("violet") + body.set_edgecolor("darkmagenta") + body.set_linewidth(2) + + for part in violin_vert: + if part == "bodies": + continue + + violin_vert[part].set_edgecolor("darkmagenta") + + if diagram_type == "box": + axis_hor.boxplot( + ordinates, + vert=False, + patch_artist=True, + boxprops=dict(facecolor="lightcoral"), + medianprops=dict(color="firebrick"), + ) + axis_vert.set_xticks([]) + axis_vert.set_xlabel("y values") + + axis_vert.boxplot( + abscissa, + vert=True, + patch_artist=True, + boxprops=dict(facecolor="lightcoral"), + medianprops=dict(color="firebrick"), + ) + axis_hor.set_yticks([]) + axis_hor.set_xlabel("x values") if __name__ == "__main__": @@ -25,4 +127,7 @@ def visualize_diagrams( abscissa, ordinates = np.random.multivariate_normal(mean, cov, size=1000).T visualize_diagrams(abscissa, ordinates, "hist") + visualize_diagrams(abscissa, ordinates, "violin") + visualize_diagrams(abscissa, ordinates, "box") + plt.show() diff --git a/solutions/sem02/lesson07/task2.py b/solutions/sem02/lesson07/task2.py index decd607ef..f6c373d83 100644 --- a/solutions/sem02/lesson07/task2.py +++ b/solutions/sem02/lesson07/task2.py @@ -1 +1,41 @@ -# ваш код (используйте функции или классы для решения данной задачи) +import matplotlib.pyplot as plt +import numpy as np + +before = [0]*4 +after = [0]*4 +file_path = 'D:/GitHub/python_mipt_dafe_tasks/solutions/sem02/lesson07/data/medic_data.json' +with open(file_path, 'r') as file: + content = file.read() + +before_part = content.split('"before"')[1].split('"after"')[0] +after_part = content.split('"after"')[1] + +before[0] = before_part.count('"I"') - before_part.count('"IV"') +before[1] = before_part.count('"II"') +before[2] = before_part.count('"III"') +before[3] = before_part.count('"IV"') + +after[0] = after_part.count('"I"') - after_part.count('"IV"') +after[1] = after_part.count('"II"') +after[2] = after_part.count('"III"') +after[3] = after_part.count('"IV"') + +figure, axis = plt.subplots(figsize=(9, 9)) + +stages = np.array(['I', 'II', 'III', 'IV']) +axis.set_xticks(np.arange(stages.size), labels=stages, weight="bold") + +x = np.arange(4) +width = 0.35 + +axis.bar(x - width/2, before, width, color='goldenrod', edgecolor='brown') +axis.bar(x + width/2, after, width, color='lightgreen', edgecolor='olive') + +axis.set_ylabel('amount of people') +axis.set_title('Mitral desease stages') +axis.legend(["before", "after"], title="Desease stages") + +figure.savefig("medic.png", bbox_inches="tight") +plt.show() + + diff --git a/solutions/sem02/lesson08/task1.py b/solutions/sem02/lesson08/task1.py index 89f88572f..42b7572ad 100644 --- a/solutions/sem02/lesson08/task1.py +++ b/solutions/sem02/lesson08/task1.py @@ -8,27 +8,60 @@ def create_modulation_animation( - modulation, - fc, - num_frames, - plot_duration, - time_step=0.001, - animation_step=0.01, - save_path="" + modulation, fc, num_frames, plot_duration, time_step=0.001, animation_step=0.01, save_path="" ) -> FuncAnimation: - # ваш код - return FuncAnimation() + abscissa = np.arange(0, plot_duration, time_step) + + def signal(abscissa, modulation, fc): + f = np.sin(2 * np.pi * fc * abscissa) + + if modulation is None: + return f + else: + return modulation(abscissa) * f + + figure, axis = plt.subplots(figsize=(16, 9)) + axis.set_xlim(0, plot_duration) + + line, *_ = axis.plot( + abscissa, + signal(abscissa, modulation, fc), + c="deeppink", + ) + + def update_frame( + frame_id: int, + ) -> tuple[plt.Line2D]: + new_x = abscissa + frame_id * animation_step + sign = signal(new_x, modulation, fc) + line.set_ydata(sign) + + return (line,) + + animation = FuncAnimation( + figure, + update_frame, + frames=num_frames, + interval=50, + blit=True, + ) + + if save_path: + animation.save("func.gif", writer="pillow", fps=24) + + return animation if __name__ == "__main__": + def modulation_function(t): - return np.cos(t * 6) + return np.cos(t * 6) - num_frames = 100 - plot_duration = np.pi / 2 - time_step = 0.001 - animation_step = np.pi / 200 - fc = 50 + num_frames = 100 + plot_duration = np.pi / 2 + time_step = 0.001 + animation_step = np.pi / 200 + fc = 50 save_path_with_modulation = "modulated_signal.gif" animation = create_modulation_animation( @@ -38,6 +71,6 @@ def modulation_function(t): plot_duration=plot_duration, time_step=time_step, animation_step=animation_step, - save_path=save_path_with_modulation + save_path=save_path_with_modulation, ) - HTML(animation.to_jshtml()) \ No newline at end of file + plt.show() diff --git a/solutions/sem02/lesson08/task2.py b/solutions/sem02/lesson08/task2.py index b677c0702..ff594f881 100644 --- a/solutions/sem02/lesson08/task2.py +++ b/solutions/sem02/lesson08/task2.py @@ -7,39 +7,153 @@ from matplotlib.animation import FuncAnimation +def animate_wave_algorithm( + maze: np.ndarray, start: tuple[int, int], end: tuple[int, int], save_path: str = "" +) -> FuncAnimation: + def wave(maze, start, end): + x, y = maze.shape + wave = np.ones(shape=maze.shape, dtype=int) * (-1) + wave[start] = 0 + free_mask = maze == 1 + history = [wave.copy()] + step = 0 + found = False + while not found: + mask = wave == step + + if not mask.any(): + break + + up = np.zeros(shape=mask.shape, dtype=bool) + down = np.zeros(shape=mask.shape, dtype=bool) + left = np.zeros(shape=mask.shape, dtype=bool) + right = np.zeros(shape=mask.shape, dtype=bool) + + up[:-1, :] = mask[1:, :] + down[1:, :] = mask[:-1, :] + left[:, :-1] = mask[:, 1:] + right[:, 1:] = mask[:, :-1] + + near = up | down | left | right + can_go_next = near & free_mask & (wave == -1) + + if not can_go_next.any(): + break + + wave[can_go_next] = step + 1 + + if wave[end] != -1: + found = True + + step += 1 + history.append(wave.copy()) + + path = [] + if found: + curr = end + path.append(curr) + while curr != start: + for nowi, nowj in [(-1, 0), (1, 0), (0, -1), (0, 1)]: + previ, prevj = curr[0] + nowi, curr[1] + nowj + if 0 <= previ < x and 0 <= prevj < y: + if wave[previ, prevj] == wave[curr] - 1: + curr = (previ, prevj) + path.append(curr) + break + + return history, path, found + + def update_frame(frame_id, axis, maze, history, path, found, h, w): + axis.clear() + + data = history[min(frame_id, len(history) - 1)] + + for i in range(h): + for j in range(w): + if maze[i, j] == 0: + color = "white" + else: + if data[i, j] >= 0: + color = "lightpink" + else: + color = "black" + axis.add_patch( + plt.Rectangle((j, h - 1 - i), 1, 1, facecolor=color, edgecolor="black") + ) + + for i in range(h): + for j in range(w): + if data[i, j] >= 0 and maze[i, j] == 1: + axis.text( + j + 0.5, + h - 1 - i + 0.5, + str(data[i, j]), + ha="center", + va="center", + fontsize=8, + ) + + axis.scatter(start[1] + 0.5, h - 1 - start[0] + 0.5, c="red", s=100) + axis.scatter(end[1] + 0.5, h - 1 - end[0] + 0.5, c="olivedrab", s=100) + + if frame_id == len(history) - 1 and found: + for i, j in path: + axis.add_patch( + plt.Rectangle((j, h - 1 - i), 1, 1, facecolor="lightgreen", edgecolor="black") + ) + + axis.set_xlim(0, w) + axis.set_ylim(0, h) + + return + + h, w = maze.shape + history, path, found = wave(maze, start, end) + + figure, axis = plt.subplots(figsize=(8, 8)) + + animation = FuncAnimation( + figure, + partial( + update_frame, axis=axis, maze=maze, history=history, path=path, found=found, h=h, w=w + ), + frames=len(history), + interval=200, + blit=False, + ) + + if save_path: + animation.save(save_path, writer="pillow", fps=5) + + return animation -def animate_wave_algorithm( - maze: np.ndarray, - start: tuple[int, int], - end: tuple[int, int], - save_path: str = "" -) -> FuncAnimation: - # ваш код - return FuncAnimation() if __name__ == "__main__": # Пример 1 - maze = np.array([ - [0, 0, 0, 0, 0, 0, 0], - [0, 1, 1, 1, 1, 1, 0], - [1, 1, 0, 1, 0, 1, 0], - [0, 0, 1, 1, 0, 1, 0], - [0, 0, 0, 0, 0, 1, 0], - [1, 1, 1, 1, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 0], - ]) + maze = np.array( + [ + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 1, 0], + [1, 1, 0, 1, 0, 1, 0], + [0, 0, 1, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0], + ] + ) start = (2, 0) end = (5, 0) save_path = "labyrinth.gif" # Укажите путь для сохранения анимации animation = animate_wave_algorithm(maze, start, end, save_path) - HTML(animation.to_jshtml()) - + plt.show() + # Пример 2 - - maze_path = "./data/maze.npy" + """ + ##maze_path = "./data/maze.npy" + maze_path = "D:/GitHub/python_mipt_dafe_tasks/solutions/sem02/lesson08/data/maze.npy" loaded_maze = np.load(maze_path) # можете поменять, если захотите запустить из других точек @@ -49,5 +163,4 @@ def animate_wave_algorithm( loaded_animation = animate_wave_algorithm(loaded_maze, start, end, loaded_save_path) HTML(loaded_animation.to_jshtml()) - - \ No newline at end of file + """ diff --git a/solutions/sem02/lesson10/task1.ipynb b/solutions/sem02/lesson10/task1.ipynb index 4b4e9e335..f7ce6cb86 100644 --- a/solutions/sem02/lesson10/task1.ipynb +++ b/solutions/sem02/lesson10/task1.ipynb @@ -1,64 +1,33 @@ { "cells": [ { - "cell_type": "markdown", - "id": "828e423a", + "cell_type": "code", + "execution_count": null, + "id": "660678f7", "metadata": {}, + "outputs": [], "source": [ - "## Задача 1. My heart will go on\n", - "\n", - "Датасет **titanic** из библиотеки `Seaborn` содержит информацию о пассажирах легендарного корабля Титаник, который затонул в 1912 году после столкновения с айсбергом. Этот набор данных часто используется для обучения и тестирования алгоритмов машинного обучения, особенно в задачах бинарной классификации (выжил / не выжил).\n", - "\n", - "**Описание данных**\n", - "\n", - "| Поле | Тип | Описание |\n", - "|--------------|----------|----------|\n", - "| `survived` | int | Выжил (1) или не выжил (0) |\n", - "| `pclass` | int | Класс билета (1, 2, 3) |\n", - "| `sex` | str | Пол (`male`/`female`) |\n", - "| `age` | float | Возраст |\n", - "| `sibsp` | int | Количество братьев/сестёр/супругов на борту |\n", - "| `parch` | int | Количество родителей/детей на борту |\n", - "| `fare` | float | Стоимость билета |\n", - "| `embarked` | str | Порт посадки (`C`=Cherbourg, `Q`=Queenstown, `S`=Southampton) |\n", - "| `class` | str | Класс билета (`First`, `Second`, `Third`) |\n", - "| `who` | str | Категория: `man`, `woman` или `child` |\n", - "| `adult_male` | bool | Является ли взрослым мужчиной |\n", - "| `deck` | str | Палуба |\n", - "| `embark_town`| str | Название порта посадки |\n", - "| `alive` | str | Выжил (`yes`/`no`) |\n", - "| `alone` | bool | Путешествовал один |\n", - "\n", - "**Загрузка датасета**" + "import numpy as np\n", + "import pandas as pd\n", + "import seaborn as sns" ] }, { "cell_type": "code", "execution_count": null, - "id": "d7b00711", + "id": "7196214e", "metadata": {}, "outputs": [], "source": [ - "import seaborn as sns\n", - "\n", - "\n", "titanic_data = sns.load_dataset(\"titanic\")\n", - "titanic_data.sample(5)" + "titanic_data.sample(5)\n" ] }, { "cell_type": "markdown", - "id": "0fdf1941", + "id": "bcd41731", "metadata": {}, "source": [ - "**Задача**\n", - "\n", - "Ниже описаны 10 небольших заданий, которые вам необходимо решить.\n", - "\n", - "**Подсказка**:\n", - "\n", - "В некоторых заданиях вам может быть полезен метод `value_counts`.\n", - "\n", "### Часть 1\n", "\n", "Определите число пропущенных данных для каждого столбца таблицы `titanic_data`." @@ -67,16 +36,18 @@ { "cell_type": "code", "execution_count": null, - "id": "cd2f1773", + "id": "7552ed11", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "mask_data_missed = titanic_data.isnull()\n", + "missed = mask_data_missed.sum()\n", + "print(missed)" ] }, { "cell_type": "markdown", - "id": "cf62022b", + "id": "e4891508", "metadata": {}, "source": [ "### Часть 2\n", @@ -89,16 +60,35 @@ { "cell_type": "code", "execution_count": null, - "id": "7e458447", + "id": "efe70eec", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "\n", + "titanic_data = titanic_data.dropna(thresh=titanic_data.shape[0]//2+1, axis=\"columns\")\n", + "\n", + "\n", + "titanic_data = titanic_data.dropna(thresh=titanic_data.shape[1]//2+1, axis=\"index\")\n", + "\n", + "print (titanic_data)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e77db6e3", + "metadata": {}, + "outputs": [], + "source": [ + "##проверка\n", + "mask_data_missed = titanic_data.isnull()\n", + "missed = mask_data_missed.sum()\n", + "print(missed)" ] }, { "cell_type": "markdown", - "id": "970caffe", + "id": "9c7eb786", "metadata": {}, "source": [ "### Часть 3\n", @@ -112,16 +102,28 @@ { "cell_type": "code", "execution_count": null, - "id": "f7db5e99", + "id": "40fffd5e", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "med_age_m = titanic_data [titanic_data['who'] == 'man'] ['age'].median()\n", + "med_age_w = titanic_data [titanic_data['who'] == 'woman'] ['age'].median()\n", + "med_age_c = titanic_data [titanic_data['who'] == 'child'] ['age'].median()\n", + "\n", + "med_age_m = round(med_age_m)\n", + "med_age_w = round(med_age_w)\n", + "med_age_c = round(med_age_c)\n", + "\n", + "titanic_data.loc[titanic_data['age'].isnull() & (titanic_data['who'] == 'man'), 'age'] = med_age_m\n", + "titanic_data.loc[titanic_data['age'].isnull() & (titanic_data['who'] == 'woman'), 'age'] = med_age_w\n", + "titanic_data.loc[titanic_data['age'].isnull() & (titanic_data['who'] == 'child'), 'age'] = med_age_c\n", + "\n", + "print (titanic_data)\n" ] }, { "cell_type": "markdown", - "id": "f3356e53", + "id": "d5e1bc6d", "metadata": {}, "source": [ "### Часть 4\n", @@ -132,16 +134,30 @@ { "cell_type": "code", "execution_count": null, - "id": "67a0c6bc", + "id": "1c182ea6", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "mask_data_missed = titanic_data.isnull()\n", + "titanic_data = titanic_data.dropna(thresh=titanic_data.shape[1]-1, axis=\"index\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b7c194d", + "metadata": {}, + "outputs": [], + "source": [ + "##проверка\n", + "mask_data_missed = titanic_data.isnull()\n", + "missed = mask_data_missed.sum()\n", + "print(missed)" ] }, { "cell_type": "markdown", - "id": "cca44237", + "id": "08986ca9", "metadata": {}, "source": [ "### Часть 5\n", @@ -152,16 +168,17 @@ { "cell_type": "code", "execution_count": null, - "id": "6a2d0ae9", + "id": "62f2e76f", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "most_city = titanic_data.value_counts('embark_town').index[0]\n", + "print (most_city)" ] }, { "cell_type": "markdown", - "id": "c13ee762", + "id": "0b71843e", "metadata": {}, "source": [ "### Часть 6\n", @@ -172,16 +189,18 @@ { "cell_type": "code", "execution_count": null, - "id": "11acb4b4", + "id": "4112b0e5", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "proc = titanic_data['survived'].sum() / titanic_data.shape[0]\n", + "proc = round(proc*100, 2)\n", + "print (proc)\n" ] }, { "cell_type": "markdown", - "id": "edfeb7d8", + "id": "684b9d7b", "metadata": {}, "source": [ "### Часть 7\n", @@ -192,16 +211,23 @@ { "cell_type": "code", "execution_count": null, - "id": "59ec7295", + "id": "b1659c38", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "survived_emb = pd.Series(\n", + " data=[((titanic_data['embarked'] == 'C') & (titanic_data['survived']== 1)).sum(),\n", + " ((titanic_data['embarked'] == 'Q') & (titanic_data['survived']== 1)).sum(),\n", + " ((titanic_data['embarked'] == 'S') & (titanic_data['survived']== 1)).sum()],\n", + " \n", + " index=['C', 'Q', 'S'])\n", + "\n", + "print(survived_emb)" ] }, { "cell_type": "markdown", - "id": "01f70ba8", + "id": "1ed4530c", "metadata": {}, "source": [ "### Часть 8\n", @@ -212,16 +238,40 @@ { "cell_type": "code", "execution_count": null, - "id": "34daca28", + "id": "a21378d9", "metadata": {}, "outputs": [], "source": [ - "# ваш код" + "survived_class = pd.Series(\n", + " data=[\n", + " round(\n", + " (((titanic_data[\"pclass\"] == 1) & (titanic_data[\"survived\"] == 1)).sum())\n", + "\n", + " / ((titanic_data[\"pclass\"] == 1).sum()) *100,\n", + " 2,\n", + " ),\n", + " round(\n", + " (((titanic_data[\"pclass\"] == 2) & (titanic_data[\"survived\"] == 1)).sum())\n", + "\n", + " / ((titanic_data[\"pclass\"] == 2).sum())*100,\n", + " 2,\n", + " ),\n", + " round(\n", + " (((titanic_data[\"pclass\"] == 3) & (titanic_data[\"survived\"] == 1)).sum())\n", + "\n", + " / ((titanic_data[\"pclass\"] == 3).sum())*100,\n", + " 2,\n", + " ),\n", + " ],\n", + " index=[1, 2, 3],\n", + ")\n", + "\n", + "print(survived_class)" ] }, { "cell_type": "markdown", - "id": "11feaf86", + "id": "019996dd", "metadata": {}, "source": [ "### Часть 9\n", @@ -231,17 +281,32 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "1fc0d667", + "execution_count": 78, + "id": "baa9a434", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "73.58\n" + ] + } + ], "source": [ - "# ваш код" + "survived_rich = round(\n", + " (((titanic_data[\"fare\"] >= 100) & (titanic_data[\"survived\"] == 1)).sum())\n", + " / ((titanic_data[\"fare\"] >= 100).sum())\n", + " * 100,\n", + " 2,\n", + ")\n", + "\n", + "print(survived_rich)" ] }, { "cell_type": "markdown", - "id": "b3f608e1", + "id": "ff097625", "metadata": {}, "source": [ "### Часть 10\n", @@ -251,26 +316,34 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "480352b6", + "execution_count": 79, + "id": "66f0bdcb", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n" + ] + } + ], "source": [ - "# ваш код" + "print(((titanic_data[\"who\"] =='child') & (titanic_data[\"alone\"])).sum())" ] }, { "cell_type": "markdown", - "id": "aac62cfd", + "id": "6355f52f", "metadata": {}, "source": [ - "Какие выводы вы можете сделать о выживших пассажирах Титаника? " + "Вывод: все выжившие пассажиры Титаника в итоге умерли. Статистика бессильна, от судьбы не уплывёшь (даже на двери). Как в пункте назначения." ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "venv (3.13.7)", "language": "python", "name": "python3" }, @@ -284,7 +357,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.9" + "version": "3.13.7" } }, "nbformat": 4, diff --git a/tests/test_data/lesson05/Vj_data.npy b/tests/test_data/lesson05/Vj_data.npy new file mode 100644 index 000000000..8b9b5f7a5 Binary files /dev/null and b/tests/test_data/lesson05/Vj_data.npy differ diff --git a/tests/test_data/lesson05/Vs_data.npy b/tests/test_data/lesson05/Vs_data.npy new file mode 100644 index 000000000..da77bd6d6 Binary files /dev/null and b/tests/test_data/lesson05/Vs_data.npy differ diff --git a/tests/test_data/lesson05/diag_A_data.npy b/tests/test_data/lesson05/diag_A_data.npy new file mode 100644 index 000000000..ea53de5c6 Binary files /dev/null and b/tests/test_data/lesson05/diag_A_data.npy differ diff --git a/tests/test_data/lesson05/y_data.npy b/tests/test_data/lesson05/y_data.npy new file mode 100644 index 000000000..656379943 Binary files /dev/null and b/tests/test_data/lesson05/y_data.npy differ diff --git a/tests/test_lesson05_tasks.py b/tests/test_lesson05_tasks.py new file mode 100644 index 000000000..c579cbe5a --- /dev/null +++ b/tests/test_lesson05_tasks.py @@ -0,0 +1,229 @@ +import os + +import numpy as np +import pytest + +from solutions.sem02.lesson05.task1 import ShapeMismatchError as Task1ShapeMismatchError +from solutions.sem02.lesson05.task1 import can_satisfy_demand +from solutions.sem02.lesson05.task2 import ShapeMismatchError as Task2ShapeMismatchError +from solutions.sem02.lesson05.task2 import get_projections_components +from solutions.sem02.lesson05.task3 import ShapeMismatchError as Task3ShapeMismatchError +from solutions.sem02.lesson05.task3 import adaptive_filter + +DATA_PATH = os.path.join("tests", "test_data", "lesson05") + + +class TestTask1: + @pytest.mark.parametrize( + "costs, resource_amounts, demand_expected, expected", + [ + pytest.param( + np.eye(2), + np.array([3.0, 3.0]), + np.array([2, 2]), + True, + id="identity_enough", + ), + pytest.param( + np.eye(2), + np.array([2.0, 2.0]), + np.array([3, 3]), + False, + id="identity_not_enough", + ), + pytest.param( + np.array([[1.0, 2.0], [3.0, 4.0]]), + np.array([10.0, 20.0]), + np.array([2, 3]), + True, + id="general_enough", + ), + pytest.param( + np.array([[1.0, 2.0], [3.0, 4.0]]), + np.array([7.0, 17.0]), + np.array([2, 3]), + False, + id="general_not_enough", + ), + pytest.param( + np.array([[1.0]]), + np.array([5.0]), + np.array([5]), + True, + id="single_resource_product_exact", + ), + pytest.param( + np.array([[1.0, 0.0, 1.0], [0.0, 1.0, 1.0]]), + np.array([3.0, 3.0]), + np.array([1, 1, 1]), + True, + id="non_square_costs_enough", + ), + pytest.param( + np.array([[1.0, 0.0, 1.0], [0.0, 1.0, 1.0]]), + np.array([1.0, 1.0]), + np.array([1, 1, 1]), + False, + id="non_square_costs_not_enough", + ), + pytest.param( + np.eye(3), + np.array([0.0, 0.0, 0.0]), + np.array([0, 0, 0]), + True, + id="zero_demand", + ), + pytest.param( + np.eye(2), + np.full(shape=2, fill_value=3), + np.full(shape=2, fill_value=2), + True, + id="notebook_satisfy", + ), + pytest.param( + np.eye(2), + np.full(shape=2, fill_value=2), + np.full(shape=2, fill_value=3), + False, + id="notebook_not_satisfy", + ), + ], + ) + def test_can_satisfy_demand( + self, costs, resource_amounts, demand_expected, expected + ): + assert can_satisfy_demand(costs, resource_amounts, demand_expected) == expected + + def test_can_satisfy_demand_validate(self): + with pytest.raises(Task1ShapeMismatchError): + can_satisfy_demand( + np.array([[1.0, 2.0, 3.0]]), + np.array([1.0, 2.0]), + np.array([1]), + ) + + with pytest.raises(Task1ShapeMismatchError): + can_satisfy_demand( + np.array([[1.0, 2.0]]), + np.array([1.0]), + np.array([1, 2, 3]), + ) + + +class TestTask2: + @pytest.mark.parametrize( + "matrix, vector, proj_expected, orth_expected", + [ + pytest.param( + np.diag([2.0, 3.0]), + np.array([1.0, 2.0]), + np.array([[1.0, 0.0], [0.0, 2.0]]), + np.array([[0.0, 2.0], [1.0, 0.0]]), + id="diagonal_basis", + ), + pytest.param( + np.array([[1.0, 0.0], [1.0, 1.0]]), + np.array([0.0, 1.0]), + np.array([[0.0, 0.0], [0.5, 0.5]]), + np.array([[0.0, 1.0], [-0.5, 0.5]]), + id="non_orthogonal_basis", + ), + pytest.param( + np.eye(3), + np.array([1.0, 2.0, 3.0]), + np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0]]), + np.array([[0.0, 2.0, 3.0], [1.0, 0.0, 3.0], [1.0, 2.0, 0.0]]), + id="identity_3d", + ), + pytest.param( + np.array([[1.0, 2.0], [2.0, 4.0]]), + np.array([0.0, 1.0]), + None, + None, + id="singular_not_basis", + ), + pytest.param( + np.array([[1.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 1.0]]), + np.array([1.0, 2.0, 3.0]), + None, + None, + id="rank_deficient_3d", + ), + pytest.param( + np.diag([2, 3]), + np.arange(start=1, stop=3), + np.array([[1, 0], [0, 2]]), + np.array([[0, 2], [1, 0]]), + id="notebook_diagonal", + ), + pytest.param( + np.array([[1, 0], [1, 1]]), + np.array([0, 1]), + np.array([[0, 0], [0.5, 0.5]]), + np.array([[0, 1], [-0.5, 0.5]]), + id="notebook_non_orthogonal", + ), + pytest.param( + np.array([[1, 2], [2, 4]]), + np.array([0, 1]), + None, + None, + id="notebook_singular", + ), + ], + ) + def test_get_projections_components( + self, matrix, vector, proj_expected, orth_expected + ): + projections, orthogonals = get_projections_components(matrix, vector) + + if proj_expected is None: + assert projections is None + assert orthogonals is None + else: + assert np.allclose(projections, proj_expected) + assert np.allclose(orthogonals, orth_expected) + + def test_get_projections_components_validate(self): + with pytest.raises(Task2ShapeMismatchError): + get_projections_components( + np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), + np.array([1.0, 2.0, 3.0]), + ) + + with pytest.raises(Task2ShapeMismatchError): + get_projections_components( + np.array([[1.0, 0.0], [0.0, 1.0]]), + np.array([1.0, 2.0, 3.0]), + ) + + +class TestTask3: + def test_adaptive_filter(self): + diag_A = np.load(os.path.join(DATA_PATH, "diag_A_data.npy")) + Vj = np.load(os.path.join(DATA_PATH, "Vj_data.npy")) + Vs = np.load(os.path.join(DATA_PATH, "Vs_data.npy")) + y_expected = np.load(os.path.join(DATA_PATH, "y_data.npy")) + + y = adaptive_filter(Vs, Vj, diag_A) + + assert y.shape == y_expected.shape + assert np.allclose(y, y_expected) + + def test_adaptive_filter_validate(self): + with pytest.raises(Task3ShapeMismatchError): + adaptive_filter( + np.array([[1.0], [2.0]]), + np.array([[1.0], [2.0], [3.0]]), + np.array([1.0]), + ) + + with pytest.raises(Task3ShapeMismatchError): + adaptive_filter( + np.array([[1.0], [2.0]]), + np.array([[1.0, 2.0], [3.0, 4.0]]), + np.array([1.0, 2.0, 3.0]), + ) + + +