В этой статье рассмотрим разные способы кластеризации и последующий анализ данных для решения задания №27 из ЕГЭ по информатике.
Термины, которые мы будем использовать: кластеризация, центр кластера.
Рассмотрим первый способ — решим задачу полностью в редакторе таблиц.
Задание 1
В некотором городе начал функционировать новый коммерческий банк Flash Money, который хочет разместить несколько отделений в городе так, чтобы всем клиентам было удобно до них добираться.
Управляющий решил провести разбиение (кластеризацию) клиентов по их расположению на карте города. В банке известны адреса всех клиентов (как координаты на карте). Кластер точек одного района — это набор координат клиентов на графике, лежащий внутри прямоугольника со сторонами длиной H и W, причём эти прямоугольники между собой не пересекаются. Стороны прямоугольников не обязательно параллельны координатным осям. Гарантируется, что такое разбиение существует и единственно для заданных размеров прямоугольников.
Задача управляющего — определить центр каждого района (кластера), чтобы разместить там отделение банка. Центром кластера будем называть точку этого кластера на графике, сумма расстояний от которой до всех остальных точек кластера (координат клиентов) минимальна. Для каждого кластера гарантируется единственность его центра.
Расстояние между двумя точками A(x1, y1) и B(x2, y2) вычисляется по формуле: [i]
В файле A хранятся данные о координатах клиентов двух районов (кластеров), где H = 4, W = 4 для каждого кластера. В каждой строке записана информация о расположении на карте одного клиента: сначала координата x, затем координата y. Значения даны в условных единицах. Известно, что количество клиентов банка не превышает 1000.
В файле B хранятся данные о координатах клиентов трёх районов (кластеров), где H = 4, W = 4 для каждого кластера. Известно, что количество клиентов банка не превышает 10 000. Структура хранения информации о клиентах в файле B аналогична файлу А.
Для каждого файла определите координаты центра каждого района (кластера), затем вычислите два числа: Px — среднее арифметическое абсцисс центров кластеров, и Py — среднее арифметическое ординат центров кластеров.
В ответе запишите четыре числа: в первой строке сначала абсолютное значение целой части произведения Px×10000, затем абсолютное значение целой части произведения Py×10000 для файла А, во второй строке — аналогичные данные для файла B.
Возможные данные одного из файлов иллюстрированы графиком. [i]
Для решения нам нужно:
- Построить диаграмму, чтобы увидеть, как точки расположены по отношению друг к другу.
- Определить кластеры — основные скопления этих точек.
- Найти то, что требуется по условию задания.
Для начала построим диаграмму.

В Excel: выделяем два столбца → «Вставка» → выбираем точечную диаграмму.
В LibreOffice: выделяем два столбца → «Вставка» → «Диаграмма» → «ХY (разброс)».

По диаграмме видно, что точки образуют два скопления: первое — там, где координата y меньше 15, второе — где y больше 15. Создадим третий столбец, в котором пропишем: =ЕСЛИ(B2>15;1;2) — проверку того, к какому кластеру принадлежит та или иная точка.
Теперь отфильтруем данные по этому столбцу и перенесём на два новых листа точки первого и второго кластеров.
Дальше найдём центр каждого кластера. Сначала разберём подробно. В новом столбце запишем формулу =(A2-A2:A132) — такая запись находит разницу ячейки А2 и всех возможных остальных координат х в столбце А.
Иногда формула срабатывает не сразу — тогда стоит попробовать зажать клавиши Ctrl + Shift + Enter.
Ещё можно выделить нужный столбец и ввести формулу в строке формул вверху.

Возведём результат в квадрат, тем самым получив часть формулы (х1-х2)**2. В следующем столбце запишем =(B2-B2:B132)^2, получив ещё одну часть формулы (у1 – у2)**2. В новом столбце складываем эти два значения формулой =C2+D2 и находим корень этой суммы в новом столбце =E2^0,5.


Посчитаем сумму столбца F — получим 145,92498973869900. Это сумма расстояний от первой точки до всех остальных.
Теперь сделаем то же самое быстрее, всего одним дополнительным столбцом: запишем =СУММ(((A2-A\$2:A\$132)^2+(B2-B\$2:B\$132)^2)^0,5). Здесь всё то же, что мы делали раньше, объединено в одну формулу. Знак $ нужен, чтобы диапазон координат, которые мы вычитаем из выбранной точки, не сдвигался. Протягиваем этот столбец до конца.

Теперь с помощью фильтра по третьему столбцу легко найти центр — минимальное число = 100,149261, достигнуто оно при х = 6,8165099, у = 24,5665558.
Скопируем формулу и просто вставим её для второго кластера, подправив диапазон (точек во втором классе окажется больше или меньше), чтобы найти его центр для координат:

=СУММ(((A2-A\$2:A\$73)^2+(B2-B\$2:B\$73)^2)^0,5), получаем минимальное число = 50,3114211 при х = 3,8579215 и у = 6,0831345.
В ответе нужно найти среднее арифметическое координат центров двух кластеров и умножить на 10000, поэтому (6,8165099+3,8579215)/2 * 10000 = 53372,16 и (24,5665558+6,0831345)/2 *10000 = 153248,5. В ответ пойдут целые части этих чисел.
Для файла 27В выполняем ровно те же действия.

Получаем такую схему. Поделим точки на три кластера с помощью формулы =ЕСЛИ(B2<0;1;ЕСЛИ(A2<0;2;3)). Если координата y меньше 0 — это первый кластер; иначе смотрим на координату x — если она меньше 0, то второй кластер, иначе третий. Переносим кластеры на три новых листа и применяем ту же формулу поиска центра.
Получаем теперь координаты трёх точек, для которых сумма из формулы получилась минимальной, и точно так же находим их среднее арифметическое (посчитано на цветных ячейках). Берём ответы по модулю.

Ответ:
53372 153248
10513 38982
Следующую задачу решим классическим способом на Python с «ручной» кластеризацией. Для разделения точек на кластеры используем Excel и построение точечной диаграммы.
Задание 2
Фрагмент звёздного неба спроецирован на плоскость с декартовой системой координат. Учёный решил провести кластеризацию полученных точек, являющихся изображениями звёзд, то есть разбить их множество на N непересекающихся непустых подмножеств (кластеров), таких что точки каждого подмножества лежат внутри прямоугольника со сторонами длиной H и W, причём эти прямоугольники между собой не пересекаются. Стороны прямоугольников не обязательно параллельны координатным осям.
Гарантируется, что такое разбиение существует и единственно для заданных размеров прямоугольников.
Для каждой планеты дана характеристика: тип цвета, тип светимости и её размер в соответствии с искомой таблицей. [i]
Полученные значения записаны в характеристике слитно: обозначение цвета, светимость (обозначается арабской цифрой) и обозначение размера планеты.
Будем называть центром кластера точку этого кластера, сумма расстояний от которой до всех остальных точек кластера минимальна. Для каждого кластера гарантируется единственность его центра. Расстояние между двумя точками на плоскости A(x1,y1) и B(x2,y2) вычисляется по формуле: [i]
В файле А хранятся данные о звёздах двух кластеров, где Н = 6,5 и W = 4,5 для каждого кластера. В каждой строке записана информация о расположении на карте одной звезды: сначала координата х, затем координата у, а затем характеристика звезды. Значения даны в условных единицах. Известно, что количество точек не превышает 1000.
В файле Б хранятся данные о звёздах трёх кластеров, где Н = 6,5 и W = 5 для каждого кластера. Известно, что количество точек не превышает 10 000. Структура хранения информации о звездах в файле Б аналогична файлу А.
Для файла А определите центры кластеров, затем вычислите: A1 — минимальное расстояние между центром кластера с наибольшим количеством точек и любым белым мега-гигантом, A2 — минимальное расстояние между двумя оранжевыми сверхгигантами, лежащими в одном кластере.
Для файла Б определите центры кластеров, затем вычислите: B1 — максимальное расстояние между центрами двух разных кластеров, B2 — сумму расстояний между центром кластера с наименьшим количеством оранжевых сверхгигантов и всеми голубыми супер-гигантами в этом же кластере.
В ответе запишите четыре числа: в первой строке — целую часть произведения A1 × 10 000, затем целую часть произведения A2 × 10 000; во второй строке — целую часть произведения В1 × 10 000, затем целую часть произведения B2 × 10 000. [i]
Строим диаграмму для файла А (для файла Б построй её самостоятельно).
Вставляем данные из файла и делаем разбиение по столбцам, выделяем первые два и создаём диаграмму в разделе «Вставка».

from math import dist
f = open(«27A_2.txt»)
cluster1 = []
cluster2 = []
for s in f:
x, y, t = s.replace(«,», «.»).split()
x, y = float(x), float(y)
color, size = t.split(t[1])
if x < 600:
cluster1.append((x, y, color, size))
else:
cluster2.append((x, y, color, size))
# Функция для нахождения центра кластера
def get_center(cluster):
min_sum = 10 ** 10
for x_c, y_c, color, size in cluster:
s = 0
for x, y, _, _ in cluster:
s += dist((x_c, y_c), (x, y))
if s < min_sum:
min_sum = s
center_of_cluster = x_c, y_c
return center_of_cluster
# Функция для поиска звёзд по цвету и размеру
def get_stars_with_common_type(cluster, c, s):
return [(x, y) for x, y, color, size in cluster if color == c and size == s]
# Функция для поиска минимального расстояния от центра до звёзд заданного типа
def get_min_dist_to_stars(center, stars):
min_dist = 10 ** 10
for point in stars:
min_dist = min(min_dist, dist(center, point))
return min_dist
# Функция для поиска минимального расстояния между двумя звёздами одного типа в кластере
def get_min_dist_between_stars(stars):
min_dist = 10 ** 10
for i in range(len(stars)):
for j in range(i + 1, len(stars)):
min_dist = min(min_dist, dist(stars[i], stars[j]))
return min_dist
center1 = get_center(cluster1)
center2 = get_center(cluster2)
# Определяем кластер с наибольшим количеством точек
if len(cluster1) >= len(cluster2):
largest_cluster_center = center1
other_cluster = cluster2
else:
largest_cluster_center = center2
other_cluster = cluster1
# A1: минимальное расстояние от центра кластера с наибольшим количеством точек до любого белого мега-гиганта (G V)
white_mega_giants = get_stars_with_common_type(cluster1 + cluster2, «G», «V»)
A1 = get_min_dist_to_stars(largest_cluster_center, white_mega_giants)
# A2: минимальное расстояние между двумя оранжевыми сверхгигантами (N IV), лежащими в одном кластере
orange_extra_giants1 = get_stars_with_common_type(cluster1, «N», «IV»)
orange_extra_giants2 = get_stars_with_common_type(cluster2, «N», «IV»)
dist1 = get_min_dist_between_stars(orange_extra_giants1)
dist2 = get_min_dist_between_stars(orange_extra_giants2)
A2 = min(dist1, dist2)
print(int(A1 * 10_000), int(A2 * 10_000))
f = open(«27B_2.txt»)
cluster1 = []
cluster2 = []
cluster3 = []
for s in f:
x, y, t = s.replace(«,», «.»).split()
x, y = float(x), float(y)
color, size = t.split(t[1])
if y < 100:
cluster1.append((x, y, color, size))
elif x > 800:
cluster2.append((x, y, color, size))
else:
cluster3.append((x, y, color, size))
center1 = get_center(cluster1)
center2 = get_center(cluster2)
center3 = get_center(cluster3)
# B1: максимальное расстояние между центрами двух разных кластеров
centers = [center1, center2, center3]
max_center_dist = 0
for i in range(len(centers)):
for j in range(i + 1, len(centers)):
max_center_dist = max(max_center_dist, dist(centers[i], centers[j]))
B1 = max_center_dist
# Функция для подсчёта количества оранжевых сверхгигантов (N IV) в кластере
def count_orange_extra_giants(cluster):
return len(get_stars_with_common_type(cluster, «N», «IV»))
# Подсчитываем количество оранжевых сверхгигантов в каждом кластере
count1 = count_orange_extra_giants(cluster1)
count2 = count_orange_extra_giants(cluster2)
count3 = count_orange_extra_giants(cluster3)
# Находим кластер с наименьшим количеством оранжевых сверхгигантов
counts = [(count1, cluster1, center1), (count2, cluster2, center2), (count3, cluster3, center3)]
min_count_cluster = min(counts, key=lambda x: x[0])
# B2: сумма расстояний между центром этого кластера и всеми голубыми супер-гигантами (S VI) в этом же кластере
blue_super_giants = get_stars_with_common_type(min_count_cluster[1], «S», «VI»)
sum_distances = 0
for point in blue_super_giants:
sum_distances += dist(min_count_cluster[2], point)
B2 = sum_distances
print(int(B1 * 10_000), int(B2 * 10_000))
Ответ:
6407 5103
6641228 1587606
Заключение
Задание №27 на кластеризацию решается по единому плану: сначала строим точечную диаграмму, чтобы увидеть скопления точек, затем разбиваем данные на кластеры по простому правилу (по координате x или y) и для каждого кластера находим центр — точку с минимальной суммой расстояний до остальных. После этого остаётся вычислить то, что просят в условии. Сделать это можно как полностью в редакторе таблиц, так и на Python, и оба способа дают один и тот же результат.