Введение в анализ данных¶

Задачи для самостоятельного решения¶

  • Данные задачи предназначены для самостоятельного прорешивания задач по желанию студента с целью освоения основой функциональности библиотек numpy, pandas, matplotlib, seaborn.
  • Решения задач сдавать не нужно, они не проверяются и не учитываются в итоговой оценке.
  • При возникновении проблем при решении задач обратитесь к материалам курса по Питону или спросите совета у ИИ-инструментов.
  • При необходимости попросите дополнительные задачи у ИИ-инструментов.
  • Также рекомендуем прорешать два упражнения на numpy в системе Яндекс.Контест.
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

sns.set_palette("Set2")

Библиотека numpy¶

Используйте библиотеку numpy для задач в этом блоке

Задача 1¶

  1. Создайте одномерный массив размером 10, составленный из чисел от 1 до 10
  2. Преобразуйте его в двумерный массив размером 2х5
In [ ]:
 

Задача 2¶

  1. Создайте 2 массива одинаковой длины и найдите их сумму, разность, произведение
  2. Найдите среднее, медиану, дисперсию и стандартное отклонение
In [ ]:
 

Задача 3¶

На вход дан одномерный массив $X$. Напишите функцию, которая выдает на вход массив из кумулятивных средних массива $X$. Иначе говоря, если $X = \left(x_1, x_2, \ldots, x_n\right)$, то ответ должен быть равен $s = \left(s_1, s_2, \ldots, s_n\right)$, где $s_k=\frac{x_1+...+x_k}{k}$.

Подсказка (кликни)

Вам поможет функция cumsum
Пример: [15, 7, 22, 11, 30, 5, 18] -> [15.0, 11.0, 14.66666667, 13.25, 15.0, 12.66666667, 13.71428571]

In [ ]:
sample = [4, 23, 69, 90, 5, 45, 19, 21]

Задача 4¶

Задан массив $X$. Для массива $X$ необходимо сделать следующее преобразование.

Необходимо написать функцию transform, которая построит новый массив, где все элементы с нечетными индексами требуется заменить на число 1. Все элементы с четными индексами нужно возвести в куб. Затем записать элементы в обратном порядке относительно их позиций.

Пример: [3, 1, 4, -1, 2, 3, 0] -> [27, 1, 64, 1, 8, 1, 0] -> [0, 1, 8, 1, 64, 1, 27]

In [ ]:
sample = [56, 20, 12, 10, 6, 84, 39, 57]

Задача 5¶

Сгенерируйте два вектора a и b в трехмерном пространстве. Заполните их случайными числами. Реализуйте их скалярное произведение с помощью numpy.

Подсказка (кликни)

Для генерации можно использовать np.random.sample

In [ ]:
def no_numpy_scalar(v1, v2):
    """
    v1: list[n] --- первый вектор-аргумент длиной n
    v2: list[n] --- второй вектор-аргумент длиной n
    return c: float  --- результат скалярного произведения векторов v1 и v2

    Функция принимает на вход два вектора длиной n
    Возвращает число, равное их скалярному произведению v1 и v2

    Реализуйте скалярное умножение векторов, не используя функции из пакета numpy

    """
    result = sum(x * y for x, y in zip(v1, v2))
    return result


def numpy_scalar(v1, v2):
    """
    v1: np.array[n] --- первый вектор-аргумент длиной n
    v2: np.array[n] --- второй вектор-аргумент длиной n
    return c: float  --- результат скалярного произведения векторов v1 и v2

    Функция принимает на вход два вектора длиной n
    Возвращает число, равное их скалярному произведению

    Реализуйте скалярное умножение векторов, используя функции из пакета numpy
    """
    result = ...
    return result
In [ ]:
# Генерация векторов
a = ...
b = ...
In [ ]:
product_1 = no_numpy_scalar(a, b)
product_2 = numpy_scalar(a, b)

# проверим корректность:
assert np.allclose(product_1, product_2)
In [ ]:
%time product_1 = no_numpy_scalar(a,b)
%time product_2 = numpy_scalar(a,b)

Задача 6¶

Для генерации матриц используем модуль random — он используется для генерации случайных объектов, функция sample создает случайную выборку. В качестве аргумента ей передается кортеж $\left(i,j\right)$, здесь $i$ — число строк, $j$ — число столбцов.

Выведите размерность (ранг) каждой матрицы с помощью функции ndim. Используйте функцию shape, что она вывела? Посмотрите на тип переменной, и сравните с типом объекта numpy созданной с помощью функции matrix

In [ ]:
a = np.random.sample((100, 100))
b = np.random.sample((100, 100))

...

Задача 7¶

Рассмотрим 3D-массив sales_data размером (4, 3, 5), который хранит данные о продажах.

Оси массива:

  • 0 — разные регионы (4 региона)
  • 1 — разные товары (3 вида товаров)
  • 2 — продажи за 5 месяцев

Пример данных:

In [ ]:
sales_data = np.random.randint(50, 200, size=(4, 3, 5))

Кроме того, имеется 2D-массив discounts размером (4, 3), который хранит скидки (в виде коэффициента, например, 0.9 означает скидку $10\%$) для каждого товара в каждом регионе:

In [ ]:
discounts = np.array(
    [
        [0.9, 0.85, 0.95],
        [0.88, 0.92, 0.87],
        [0.93, 0.89, 0.91],
        [0.86, 0.94, 0.90],
    ]
)

Примените скидки ко всем месяцам продаж используя broadcasting, чтобы скорректировать sales_data.

In [ ]:
 

Вычислить общую сумму продаж после скидок для каждого региона (результат должен быть размерности (4,)).

In [ ]:
 

Задача 8¶

Вам предлагается перемножить две квадратные матрицы двумя способами — без использования пакета numpy и с ним.

In [ ]:
def no_numpy_mult(a, b):
    """
    A: list of "size" lists, each contains "size" floats --- первая матрица-аргумент
    B: list of "size" lists, each contains "size" floats --- вторая матрица-аргумент
    return C: list of "size" lists, each contains "size" floats --- матрица, являющаяся результатом умножения матриц a и b

    Функция принимает на вход две матрицы: A и B размерностью size x size
    Возвращает матрицу их произведения A * B = C
    """

    size = len(a)
    result = [[0] * size for _ in range(size)]
    for i in range(size):
        for j in range(size):
            for k in range(size):
                result[i][j] += a[i][k] * b[k][j]
    return result


def numpy_mult(a, b):
    """
    A: np.ndarray[size, size] --- первая матрица-аргумент
    B: np.ndarray[size, size] --- вторая матрица-аргумент
    return C: np.array[size, size] --- матрица, являющаяся результатом умножения матриц A и B

    Функция принимает на вход две матрицы: A и B размерностью size x size
    Возвращает матрицу их произведения A * B = C

    Реализуйте умножение матриц, используя функции из пакета numpy
    """

    pass

Проверьте корректность и сравните время выполнения.

In [ ]:
M1 = no_numpy_mult(a, b)
M2 = numpy_mult(a, b)

# проверим корректность
assert np.allclose(np.array(M1), M2)
In [ ]:
%time no_numpy_mult(a, b)
%time numpy_mult(a, b)

Задача 9¶

Создайте случайно заполненную матрицу 5x5 и проведите следующие действия с ней:

  1. Транспонирование
  2. Нахождение детерминанта
  3. Нахождение обратной матрицы
  4. Создайте и объедините 2 матрицы сначала по столбцу, а потом по строкам
  5. Разбейте исходную матрицу
In [ ]:
matrix = ...
transposed_matrix = ...
det = ...
inv_matrix = ...

print("Исходная матрица:\n", matrix)
print("Транспонированная матрица:\n", transposed_matrix)
print("Определитель:\n", det)
print("Обратная матрица:\n", inv_matrix)
In [ ]:
coancated_matrix_col = ...
coancated_matrix_row = ...
splited_matrix_col = ...
coancated_matrix_row = ...

print("Объединение по столбцу\n", coancated_matrix_col)
print("Объединение по строке\n", coancated_matrix_row)
print("Разбитая матрица по столбцу\n", splited_matrix_col)
print("Разбитая матрица по строке\n", coancated_matrix_row)

Библиотеки matplotlib и seaborn¶

Задача 1¶

Нарисуйте график синусоидальной волны для диапазона значений от 0 до $2\pi$. Добавьте заголовок, метки осей и сетку.

Создайте массива значений от 0 до $2\pi$ и вычислите синус для каждого значения в массиве.

Подсказка (кликни)

Используйте функции np.linspace для создания массива значений и np.sin для вычисления синуса.

In [ ]:
...

Постройте график

In [ ]:
...

Задача 2¶

Сгенерируйте 1000 случайных чисел и постройте гистограмму их распределения.

In [ ]:
...

Задача 3¶

Создайте массив sizes, который будет состоять из $10^2, 10^3, 10^4, 10^5$ чисел. Числа должны быть целыми.

Постройте plt.subplots в виде строки из 4 графиков. Параметр bins укажите 100. На каждом графике нарисуйте гистограмму массива заданного размера из массива sizes. Подпишите, какой размер массивы к какому графику относится.

Подсказка

Для создания массива можно воспользоваться np.logspace
Подписи осей создаются как axs[i].set('параметры')

In [ ]:
sizes = ...
In [ ]:
fig, axs = plt.subplots(figsize="размеры графика", ncols="колличество колонок")

...

plt.show()

Задача 4¶

Создайте анимацию, показывающую распространение волны в двумерной плоскости. Волна должна начинаться из центра и распространяться во все стороны. Используйте цветовую карту для визуализации амплитуды волны.

Требования:

  1. Используйте библиотеку matplotlib для создания анимации.
  2. Волна должна быть синусоидальной.
  3. Анимация должна показывать распространение волны от центра к краям.
  4. Используйте цветовую карту для визуализации амплитуды волны.
  5. Добавьте заголовок и цветовую шкалу.
Подсказка

Используйте numpy.meshgrid для создания сетки координат.
Используйте matplotlib.animation.FuncAnimation для создания анимации.
Используйте matplotlib.pyplot.imshow или matplotlib.pyplot.pcolormesh для визуализации волны.

Для начала построим статическую картину распределения

In [ ]:
# Параметры волны
size = ...  # размер сетки
amplitude = ...  # амплитуда волны
frequency = ...  # частота волны
In [ ]:
# Создаем сетку координат
x = np.linspace()
y = np.linspace()
X, Y = ...

# Функция волны
Z = ...
In [ ]:
# Построение статического изображения
...

Теперь изменим функцию так, чтобы она обновлялась покадрово

Подсказка

Синус зависит от frames

In [ ]:
# Параметры волны
frames = 100  # количество кадров
In [ ]:
# Функция для обновления анимации


def update(frame):
    Z = ...
    cax.set_array(Z)
    ax.set_title(f"Frame {frame}")
    return (cax,)
In [ ]:
import matplotlib.animation as animation
from IPython.display import HTML

# Создаем фигуру и оси
fig, ax = plt.subplots()
cax = ax.imshow(
    np.zeros((size, size)), cmap="viridis", extent=(-5, 5, -5, 5), animated=True
)
fig.colorbar(cax, ax=ax)

# Создаем анимацию
ani = animation.FuncAnimation(
    fig="объект графика",
    func="функция задающая распределение волны",
    frames=frames,
    interval=50,
    blit=True,
)

# Отображаем анимацию в Colab
HTML(ani.to_jshtml())

Задача 5¶

Создайте тепловую карту корреляции для набора данных, содержащего информацию о различных характеристиках автомобилей (например, цена, мощность двигателя, расход топлива и т.д.). Визуализация должна показывать, как различные характеристики коррелируют друг с другом.

Требования:

  1. Используйте библиотеку Seaborn для создания тепловой карты корреляции.
  2. Добавьте аннотации к каждой ячейке тепловой карты, показывающие значения корреляции.
  3. Используйте цветовую шкалу для визуализации корреляции.
  4. Добавьте заголовок и метки осей.
Подсказка

Используйте pandas.DataFrame.corr для вычисления матрицы корреляции.
Используйте seaborn.heatmap для создания тепловой карты корреляции.

In [ ]:
# Загрузка набора данных
data = sns.load_dataset("mpg")
# Удаление категориальных переменных
data = data.select_dtypes(include=["float64", "int64"])
In [ ]:
# Вычисление матрицы корреляции
...
In [ ]:
# Создание тепловой карты корреляции
...

Задача 6¶

Сгенерируйте набор данных, содержащий две переменные, и визуализируйте их с помощью scatter plot. Добавьте линию регрессии на график.

Подсказка

Используйте numpy.random.normal для генерации данных. Используйте seaborn.scatterplot для построения scatter plot. Используйте seaborn.regplot для добавления линии регрессии.

In [ ]:
# Генерация данных
x = ...  # независимая переменная
In [ ]:
y = 2 * x + np.random.normal(
    loc=0, scale=1, size=100
)  # зависимаяпеременная (таргет)
In [ ]:
# Построение scatter plot и линии регрессии
...

Библиотека pandas¶

Задача 1¶

Это структура данных, которую можно рассматривать как одну колонку таблицы, одномерный массив.

Создайте объект Series на основе имеющихся данных и выведите месяц своего рождения, а также промежуток месяцев, когда бы вы хотели родиться (месяца должны быть последовательны):

Подсказка

Можно воспользоваться методами .loc или .iloc

In [ ]:
# Полный список месяцев
months = [
    "Январь",
    "Февраль",
    "Март",
    "Апрель",
    "Май",
    "Июнь",
    "Июль",
    "Август",
    "Сентябрь",
    "Октябрь",
    "Ноябрь",
    "Декабрь",
]

# Полный список индексов
indexes = [
    "Первый",
    "Второй",
    "Третий",
    "Четвёртый",
    "Пятый",
    "Шестой",
    "Седьмой",
    "Восьмой",
    "Девятый",
    "Десятый",
    "Одиннадцатый",
    "Двенадцатый",
]

# Создание Series
...

Задача 2¶

  1. Создайте Series с числовыми данными (случайным образом в диапазоне от 1 до 100)

  2. Вычислите среднее значение, сумму и максимальное значение

  3. Отфильтруйте значения, которые больше заданного порога (например 30)

In [ ]:
 

Задача 3¶

Создайте Series с числовыми данными, сгенерированные случайным образом в диапазоне от 1 до 100, и примените функцию для преобразования значений (например, умножение на 2).

Подсказка

Можно использовать метод apply() для применения функции. Однако он работает медленнее, чем векторизированные операции, поэтому им стоит пользоваться только в крайних случаях

In [ ]:
def complex_transform(x):
    ...
    return ...


def apply_complex_transform(series):
    """Применяет сложное преобразование к каждому элементу Series с
    использованием метода apply.

    Parameters:
    series (pd.Series): Входная Series с числовыми данными.

    Returns:
    pd.Series: Преобразованная Series.
    """
    return ...


def vectorized_operation(series):
    """Выполняет векторизированную операцию умножения всех элементов Series на 2.

    Parameters:
    series (pd.Series): Входная Series с числовыми данными.

    Returns:
    pd.Series: Преобразованная Series.
    """
    return ...

Проверим работу и время выполнения

In [ ]:
# Создание объекта Series
...

# Результаты преобразований
...
In [ ]:
# Замеряем время выполнения функции с apply
%%time
transformed_series_apply = apply_complex_transform(series)
In [ ]:
# Замеряем время выполнения векторизированной операции
%%time
transformed_series_vectorized = vectorized_operation(series)

Задача 4¶

Пусть есть два объекта Series, содержащих данные о продажах за два разных месяца. Объедините эти данные и визуализируйте их с помощью линейного графика, чтобы показать изменение продаж по дням.

Подсказка

Для улучшения визуализации можно воспользоваться plt.xticks Для объединения даты можно воспользоваться pd.concat

In [ ]:
# Создание данных о продажах за первый месяц
sales_january = pd.Series(
    [100, 150, 200, 250, 300, 350, 400],
    index=pd.date_range(start="2023-01-01", periods=7, freq="D"),
)

# Создание данных о продажах за второй месяц
sales_february = pd.Series(
    [450, 500, 550, 600, 650, 700, 750],
    index=pd.date_range(start="2023-02-01", periods=7, freq="D"),
)

# Объединение данных
...

Задача 5¶

Объект DataFrame лучше всего объяснять на примере обычной таблицы. В таблице есть строки и столбцы. Столбцами в объекте DataFrame выступают объекты Series, а их элементы будут строками.

Создайте объект DataFrame. Проще всего сделать это из словаря, в котором ключ это название колонки, значения — данные массива. Данные могут быть как текстового так и числового вида.

In [ ]:
 

Задача 7¶

Повторите задания 2—3 из этого блока, но только для объекта DataFrame, с соответствующими методами

In [ ]:
 

Задача 8¶

Пусть есть DataFrame, содержащий данные о продажах различных товаров в нескольких категориях. Вычислите общую сумму продаж для каждой категории и визуализируйте результаты с помощью столбчатой диаграммы.

Подсказка

Используйте метод groupby() для применения функции.

In [ ]:
data = pd.DataFrame(
    {
        "Category": [
            "Electronics",
            "Books",
            "Electronics",
            "Books",
            "Furniture",
            "Electronics",
            "Furniture",
        ],
        "Sales": [100, 150, 200, 250, 300, 350, 400],
    }
)

...

Задача 9¶

Пусть есть два DataFrame, содержащих данные о продажах и клиентах. Объедините эти данные по общему ключу и визуализируйте распределение продаж по возрасту клиентов.

In [ ]:
# Создание DataFrame с данными о продажах
sales_data = pd.DataFrame(
    {"ClientID": [1, 2, 3, 4, 5], "Sales": [100, 150, 200, 250, 300]}
)

# Создание DataFrame с данными о клиентах
clients_data = pd.DataFrame(
    {"ClientID": [1, 2, 3, 4, 5], "Age": [25, 30, 35, 40, 45]}
)

...

Задача 10¶

Пусть есть DataFrame, содержащий данные о различных характеристиках автомобилей. Вычислите корреляционную матрицу и визуализируйте её с помощью тепловой карты

In [ ]:
# Создание DataFrame с данными о характеристиках автомобилей
np.random.seed(0)  # Для воспроизводимости результатов

data = pd.DataFrame(
    {
        "Price": np.random.randint(20000, 50000, size=100),
        "Mileage": np.random.randint(1000, 50000, size=100),
        "Horsepower": np.random.randint(100, 400, size=100),
        "FuelEfficiency": np.random.randint(15, 40, size=100),
        "Age": np.random.randint(1, 10, size=100),
    }
)

...

Что можно сказать исходя из полученного рисунка?