#python #matplotlib #plot #cluster-analysis #scatter-plot
#python #matplotlib #график #кластерный анализ #точечная диаграмма
Вопрос:
Я выполняю кластеризацию и пытаюсь отобразить результат с помощью функции точечной диаграммы matplotlib.
Фиктивный набор данных :
x = [48.959 49.758 49.887 50.593 50.683 ]
y = [122.310 121.29 120.525 120.252 119.509]
z = [136.993 133.128 143.710 129.088 139.860]
Я строю x, y и использую z в качестве цветовой оси, используя следующий код
plt.scatter(
x=x, y=y, c=z, label="CO2 Emissions Saved Cumulative", cmap=cm1)
Вот как это выглядит для всех данных
Теперь я выполнил кластеризацию K средних в своем наборе данных и нашел три кластера. Например
[0 0 0 0 0 2 1 2 1 2 1 1 2 1 1 1 2 2 2 2 2]
Я нашел следующее решение для их построения, дифференцируя стиль маркера
ax.scatter(x[cluster == 0], y[cluster == 0], marker="*")
ax.scatter(x[cluster == 1], y[cluster == 1], marker="^")
ax.scatter(x[cluster == 2], y[cluster == 2], marker="s")
теперь проблема заключается в том, что при использовании этого метода он перезаписывает ось цвета, как показано в этом примере изображения
пример кластерного графика
Как я могу избежать этого, чтобы не изменять цветовую ось маркеров и по-прежнему использовать значения z по умолчанию для цветовой оси. Я хочу, чтобы график изменял стиль маркера только в соответствии с данными кластера. и не изменять цвет на основе данных кластера. Спасибо
Ответ №1:
Вам необходимо масштабировать z-значение каждого кластера до одного и того же масштаба, чтобы у вас была единая цветовая полоса для 3 точечных графиков. Для этого вы можете использовать Normalize
объект и передать эту нормализацию в scatter using norm=
.
x = np.array([48.959, 49.758, 49.887, 50.593, 50.683 ])
y = np.array([122.310, 121.29, 120.525, 120.252, 119.509])
z = np.array([136.993, 133.128, 143.710, 129.088, 139.860])
cluster = np.array([0, 1, 0, 2, 2])
mini, maxi = np.min(z), np.max(z)
norm = plt.Normalize(mini, maxi)
fig, ax = plt.subplots()
a = ax.scatter(x[cluster == 0], y[cluster == 0], marker="*", c=z[cluster == 0], norm=norm)
a = ax.scatter(x[cluster == 1], y[cluster == 1], marker="^", c=z[cluster == 1], norm=norm)
a = ax.scatter(x[cluster == 2], y[cluster == 2], marker="s", c=z[cluster == 2], norm=norm)
fig.colorbar(a)
Комментарии:
1. Спасибо за ваш ответ @Diziet. Тем не менее, я хочу сохранить тот же масштаб, что и на первом прикрепленном изображении. Единственное изменение, которое я хочу добавить к нему, — это иметь стиль маркера, основанный на кластере. в предложенном вами решении отображается диапазон цветовой полосы только от 0-1
2. а также, зачем нормализовать значения z? кластеризация была выполнена для всего набора данных (x, y, z)
3. Я добиваюсь того же, просто добавляя c = z[cluster == 0] . Результаты этого и вашего решения аналогичны. Это не то, чего я хотел.
4. Цель состоит в том, чтобы масштабировать z-значение каждого кластера до одного и того же масштаба, чтобы у вас была единая цветовая полоса для 3 точечных графиков. Я включил полный код
5. потрясающе, понял. именно то, что я хотел. Спасибо.
Ответ №2:
Менее подробным и более надежным решением для больших наборов данных является использование библиотеки pandas
and seaborn
:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
x = [48.959, 49.758, 49.887, 50.593, 50.683 ]
y = [122.310, 121.29, 120.525, 120.252, 119.509]
z = [136.993, 133.128, 143.710, 129.088, 139.860]
kmean = np.array([0, 1, 0, 2, 2])
df = pd.DataFrame({'x':x,'y':y,'z':z, 'km_z':kmean})
sns.scatterplot(data = df, x='x', y='y', hue='km_z', style='km_z')
который выдает следующий результат
Кроме того, вы можете использовать pandas.cut
функцию для построения ячеек (это то, что мне регулярно нужно для создания графиков, где я могу использовать третье непрерывное значение в качестве параметра). Способ его использования :
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
x = [48.959, 49.758, 49.887, 50.593, 50.683 ]
y = [122.310, 121.29, 120.525, 120.252, 119.509]
z = [136.993, 133.128, 143.710, 129.088, 139.860]
df = pd.DataFrame({'x':x,'y':y,'z':z})
df['bins'] = pd.cut(df.z, bins=3)
sns.scatterplot(data = df, x='x', y='y', hue='bins', style='bins')
и это приводит к следующему примеру:
Я использовал последний метод для создания графиков, подобных следующему: