Добавил:
baraevaliza
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабы по ОМО 2025 / Baraeva_Elizaveta_lb1
.pdf
11
plt.show()
Рисунок 1.6.2 – Гистограммы распределения для каждого признака
1.6.1. Постройте гистограммы для разного количества столбцов:
5,10,15,20,30. Выберите на ваш взгляд такое количество столбцов,
который лучшие образом описывает форму распределения
признаков.
Для выбора количества столбцов возьмем, например, столбец 'sepal
length (cm)'. Сначала задаётся список, содержащий значения количества
столбцов. Затем создаётся график с пятью подграфиками в один ряд. В цикле
строятся гистограммы для столбца 'sepal length (cm)' с разным количеством
столбцов. Гистограммы оформляются с чёрными границами столбцов, а
также получают заголовки, указывающие количество столбцов, подписи осей
X и Y. В конце вызывается plt.tight_layout(), чтобы корректно разместить
графики, а затем plt.show() отображает результат. Реализация приведена в
Листинге 1.6.1.1. График гистограммы представлен на Рисунке 1.6.1.2.
Листинг 1.6.1.1 – Реализация рисования гистограммы распределения с
разным количеством столбцов
bins_list = [5, 10, 15, 20, 30]
fig, axs = plt.subplots(1, 5, figsize=(20, 5))
for i in range(5):

12
axs[i].hist(df['sepal length (cm)'], bins=bins_list[i],
edgecolor='black')
axs[i].set_title(f'bins={bins_list[i]}')
axs[i].set_xlabel('sepal length (cm)')
axs[i].set_ylabel('Count')
plt.tight_layout()
plt.show()
Рисунок 1.6.1.2 – Гистограммы распределения с разным количеством
столбцов
Как мне кажется, оптимальное количество столбцов – 10, поскольку при
таком разбиении гистограмма сохраняет информативность и не теряет
важные особенности распределения.
1.6.2. Сделайте на каждой гистограмме разделение по цвету согласно
классу. Проведите это в двух режимах, когда гистограммы
накладываются/суммируются и когда пересекаются. Далее
используйте режим с пересечением.
Сначала создаётся график с четырьмя подграфиками в один ряд. Затем
для каждого признака строится гистограмма с помощью sns.histplot, где hue –
название столбца для группировки данных по цвету, bins – количество
столбцов, multiple – режим гистограммы, в данном случае режим наложения.
Каждая гистограмма получает заголовок. После цикла вызывается

13
plt.tight_layout(), чтобы корректно разместить графики, а затем plt.show()
отображает результат. Реализация приведена в Листинге 1.6.2.1. График
гистограммы представлен на Рисунке 1.6.2.2.
Листинг 1.6.2.1 – Реализация рисования гистограммы распределения в
режиме наложения
fig, axes = plt.subplots(1, 4, figsize=(20, 5))
for ax, column in zip(axes, df.columns[:-1]):
sns.histplot(data=df, x=column, hue='target', bins=10,
multiple='stack', ax=ax)
fig.suptitle(f'Режим наложения')
plt.tight_layout()
plt.show()
Рисунок 1.6.2.2 – Гистограммы распределения в режиме наложения
Для режима пересечения зададим параметр multiple='layer'. График
гистограммы представлен на Рисунке 1.6.2.3.
Рисунок 1.6.2.3 – Гистограммы распределения в режиме пересечения

14
1.7. Постройте гистограммы, чтобы вместо столбцов изображались
ступеньки.
Для построения гистограммы в виде ступенек используем element='step'.
Реализация приведена в Листинге 1.7.1. График гистограммы представлен на
Рисунке 1.7.2.
Листинг 1.7.1 – Реализация рисования гистограммы распределения
ступеньками
fig, axes = plt.subplots(1, 4, figsize=(20, 5))
for ax, column in zip(axes, df.columns[:-1]):
sns.histplot(data=df, x=column, hue='target', bins=10,
multiple='layer', element='step', ax=ax)
fig.suptitle(f'Режим пересечения')
plt.tight_layout()
plt.show()
Рисунок 1.7.2 – Гистограммы распределения ступеньками
1.8. Добавьте на гистограммы график ядерной оценки плотности.
Для добавления на гистограммы графика ядерной оценки плотности
используем kde=True. Реализация представлена в Листинге 1.8.1. Результат
представлен на Рисунке 1.8.2.

15
Листинг 1.8.1 – Реализация рисования гистограммы распределения с
добавлением ядерной оценки плотности.
fig, axes = plt.subplots(1, 4, figsize=(20, 5))
for ax, column in zip(axes, df.columns[:-1]):
sns.histplot(data=df, x=column, hue='target', bins=10,
multiple='layer', element='step', ax=ax, kde=True)
fig.suptitle(f'Режим пересечения')
plt.tight_layout()
plt.show()
Рисунок 1.8.2 – Гистограммы распределения с добавлением ядерной
оценки плотности
2. Изучение набора данных iris.csv с использованием NumPy:
2.1. Загрузите данные из файла как массив NumPy
Для загрузки данных используем функцию numpy.genfromtxt. Она
загружает данные из файла, разделяя их запятыми. skip_header=1 –
пропускает первую строку, если в файле есть заголовки. Реализация
представлена в Листинге 2.1.1.
Листинг 2.1.1 – Загрузка данных из файла как массив NumPy
import numpy as np
data = np.genfromtxt("iris.csv", delimiter=",", skip_header=1)
2.2. Выведите первые 10 наблюдений набора данных.

16
Для вывода первых 10 наблюдений используем срез. Реализация
представлена в Листинге 2.2.1. Результат приведен в Листинге 2.2.2.
Листинг 2.2.1 – Вывод первых десяти записей датасета
print(data[:10])
Листинг 2.2.2 – Первые десять записей датасета
[[0. 5.1 3.5 1.4 0.2 0. ]
[1. 4.9 3. 1.4 0.2 0. ]
[2. 4.7 3.2 1.3 0.2 0. ]
[3. 4.6 3.1 1.5 0.2 0. ]
[4. 5. 3.6 1.4 0.2 0. ]
[5. 5.4 3.9 1.7 0.4 0. ]
[6. 4.6 3.4 1.4 0.3 0. ]
[7. 5. 3.4 1.5 0.2 0. ]
[8. 4.4 2.9 1.4 0.2 0. ]
[9. 4.9 3.1 1.5 0.1 0. ]]
2.3. Рассчитайте характеристики, полученные методом describe в п. 1.3 с
использованием методов NumPy. Обращайте внимание на то, где
оценка смещенная, а где нет.
Для расчета характеристик используются методы: shape[0], который
определяет количество наблюдений; mean, который рассчитывает среднее
значение по каждому признаку; std, который рассчитывает стандартное
отклонение с несмещённой оценкой (ddof=1); min и max, которые
рассчитывают минимальное и максимальное значения; percentile, который
вычисляет квартили (25%, 50%, 75%). Реализация приведена в Листинге
2.3.1. Результат представлен в Листинге 2.3.2.
Листинг 2.3.1 – Расчет характеристик датасета.
count = data.shape[0]
mean = np.mean(data, axis=0)
std = np.std(data, axis=0, ddof=1)
min_val = np.min(data, axis=0)
percentiles_25 = np.percentile(data, 25, axis=0)
percentiles_50 = np.percentile(data, 50, axis=0)

17
percentiles_75 = np.percentile(data, 75, axis=0)
max_val = np.max(data, axis=0)
print('sepal length (cm), sepal width (cm), petal length (cm),
petal width (cm)')
print(f"count: {count}")
print(f"mean: {mean}")
print(f"std: {std}")
print(f"min: {min_val}")
print(f"25%: {percentiles_25}")
print(f"50%: {percentiles_50}")
print(f"75%: {percentiles_75}")
print(f"max: {max_val}")
Листинг 2.3.2 – Результат расчета характеристик датасета.
sepal length (cm), sepal width (cm), petal length (cm), petal
width (cm)
count: 150
mean: [74.5 5.84333333 3.05733333 3.758
1.19933333 1. ]
std: [43.44536799 0.82806613 0.43586628 1.76529823
0.76223767 0.81923192]
min: [0. 4.3 2. 1. 0.1 0. ]
25%: [37.25 5.1 2.8 1.6 0.3 0. ]
50%: [74.5 5.8 3. 4.35 1.3 1. ]
75%: [111.75 6.4 3.3 5.1 1.8 2. ]
max: [149. 7.9 4.4 6.9 2.5 2. ]
3. Изучение набора данных вашего варианта:
3.1. Оцените и опишите набор данных вашего варианта с
использованием методов, рассмотренных ранее. Сделайте выводы о
кол-во классов, наличию выбросов, пересечении классов, и т.д.
Для начала загрузим данные из файла в датафрейм и уберем лишний
первый столбец. Далее заменим метки классов: 0 – Iris-setosa, 1 – Irisversicolor, 2 – Iris-virginica, и выведем основные статистические
характеристики. Реализация приведена в Листинге 3.1.1. Результат
представлен в Листинге 3.1.2.
Листинг 3.1.1 – Загрузка датасета и вывод характеристик.

18
df = pd.read_csv("lab1_var1.csv", index_col=0)
df["label"] = df["label"].replace([0, 1, 2], ["Iris-setosa",
"Iris-versicolor", "Iris-virginica"])
print(df.describe())
Листинг 3.1.2 – Статистические характеристики датасета.
var1
var2
var3
var4
label
count
200.000000
200.000000
200.000000
200.000000
200.000000
mean
0.116475
-0.110263
-0.167975
0.035150
0.995000
std
2.725473
2.707951
3.729149
2.649211
0.817506
min
-5.467196
-4.597760
-7.753001
-4.694267
0.000000
25%
-2.523431
-2.785206
-3.393294
-2.346640
0.000000
50%
0.338841
-0.496754
0.429499
0.124045
1.000000
75%
2.689858
2.513700
2.989684
2.504390
2.000000
max
4.439297
5.207049
7.338198
4.814143
2.000000
Реализация построения графиков оценки ядерной плотности, диаграмм
рассеивания и двумерной оценки ядерной плотности каждого признака
представлена в Листинге 3.1.3. Результаты приведены на Рисунке 3.1.4.
Листинг 3.1.3 – Реализация построения графиков оценки ядерной плотности,
диаграмм рассеивания и двумерной оценки ядерной плотности каждого
признака.
g = sns.PairGrid(df, hue="label", palette="tab10",
diag_sharey=False)
g.map_upper(sns.scatterplot)
g.map_lower(sns.kdeplot)
g.map_diag(sns.kdeplot)
g.add_legend()
plt.show()

19
Рисунок 3.1.4 – Графики оценки ядерной плотности, диаграммы
рассеивания и двумерной оценки ядерной плотности каждого признака
На графиках видно, что iris-setosa четко отделяется от остальных классов
по переменным var2 и var3. В диаграммах рассеяния можно наблюдать, как
его точки образуют отдельные кластеры. Ядерная оценка плотности также
подтверждает, что распределение этого класса не пересекается с другими.
Iris-versicolor и iris-virginica, напротив, имеют значительное перекрытие,
особенно по переменным var1 и var4. Это хорошо заметно на диаграммах
рассеяния, где их точки накладываются друг на друга. Контурные линии KDE
подтверждают частичное пересечение этих двух классов, что может
затруднить их классификацию. В некоторых распределениях можно увидеть
точки, значительно удаленные от основной массы данных, что может
указывать на наличие выбросов. Например, по переменным var3 и var4

20
видно, что некоторые точки выходят за пределы основных плотностей
распределений, особенно у iris-virginica. Также между некоторыми
переменными наблюдается линейная зависимость, например, между var1 и
var3. В проекциях классы располагаются вдоль диагональных линий, что
указывает на возможные корреляции между переменными.
Построение гистограмм распределения для каждого признака с
графиком ядерной оценки плотности представлено в Листинге 3.1.5.
Результат приведен на Рисунке 3.1.6.
Листинг 3.1.5 – Реализация построения гистограмм распределения для
каждого признака с графиком ядерной оценки плотности.
fig, axes = plt.subplots(1, 4, figsize=(20, 5))
for ax, column in zip(axes, df.columns[:-1]):
sns.histplot(data=df, x=column, hue='label', bins=15,
multiple='layer', element='step', ax=ax, kde=True)
fig.suptitle(f'Распределение признаков с графиком ядерной
оценки плотности')
plt.tight_layout()
plt.show()
Рисунок 3.1.6 – Гистограммы распределения для каждого признака с
графиком ядерной оценки плотности
По гистограмме можно сказать, что iris-setosa четко отделяется, тогда как
iris-versicolor и iris-virginica частично пересекаются, что усложняет их
Соседние файлы в папке Лабы по ОМО 2025
