我想绘制具有不同聚类的数据集。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn.cluster
rng = np.random.default_rng(seed=5)
df_1_3 = pd.DataFrame(rng.normal(loc=(1, 3), size=(30, 2), scale=0.50), columns=["x", "y"])
df_5_1 = pd.DataFrame(rng.normal(loc=(5, 1), size=(30, 2), scale=0.25), columns=["x", "y"])
df_5_5 = pd.DataFrame(rng.normal(loc=(5, 5), size=(30, 2), scale=0.25), columns=["x", "y"])
df = pd.concat([df_1_3, df_5_1, df_5_5], keys=["df_1_3", "df_5_1", "df_5_5"])
聚类算法将计算聚类标签:
model = sklearn.cluster.AgglomerativeClustering(...)
df["cluster"] = model.fit_predict(df[["x", "y"]]) # [0, 0, 0, ... 1, 1, 1 ... 2, 2, 2]
df["cluster"] = df["cluster"].astype("category")
我想在一张图中可视化数据。每个原始数据应通过单独的标记进行区分,并且标签应通过颜色可视化。
澄清一下,如果您将所有三个数据的来源设置得彼此接近。该算法将仅创建一个簇(也称为一种类别/颜色),但标记应取决于原始的
keys
、'df_1_3'
、'df_5_1'
和 'df_5_5'
。
实际上我几乎得到了结果:
fig, ax = plt.subplots()
for marker, (name, sdf) in zip(["o", "s", "^", "d"], df.groupby(level=0)):
sdf.plot.scatter(x="x", y="y", c="cluster", marker=marker, cmap="viridis", ax=ax)
如何去掉多余的颜色条?
使用seaborn,你可以在不使用for循环的情况下做到这一点,并获得更清晰的绘图:
import seaborn as sns
sns.scatterplot(data=df, x='x', y='y', hue='cluster', style='cluster', markers=["o", "^", "d"], palette="viridis")
要保持颜色和标记分开,最好重置数据帧索引,并使用索引的
keys
中的 level=0
作为标记。
# reset the index
df = df.reset_index(level=0, names=['key'])
# plot
ax = sns.scatterplot(data=df, x='x', y='y', hue='cluster', style='key', markers=["o", "^", "d"], palette="viridis")
sns.move_legend(ax, bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)
df.head()
之后 df.reset_index(level=0, names=['key'])
key x y cluster
0 df_1_3 0.599034 2.337821 0
1 df_1_3 0.875819 3.210223 0
2 df_1_3 1.568023 3.054853 0
3 df_1_3 0.723676 2.607610 0
4 df_1_3 1.374373 3.817392 0
我尝试用这个来模拟你的代码。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
rng = np.random
df_1_3 = pd.DataFrame(rng.normal(loc=(1, 3), size=(30, 2), scale=0.50), columns=["x", "y"])
df_5_1 = pd.DataFrame(rng.normal(loc=(5, 1), size=(30, 2), scale=0.25), columns=["x", "y"])
df_5_5 = pd.DataFrame(rng.normal(loc=(5, 5), size=(30, 2), scale=0.25), columns=["x", "y"])
df_1_3["cluster"] = "0"
df_5_1["cluster"] = "1"
df_5_5["cluster"] = "2"
df = pd.concat([df_1_3, df_5_1, df_5_5], keys=["df_1_3", "df_5_1", "df_5_5"])
df["cluster"] = df["cluster"].astype("category")
这是满足您需要的部分:
fig, ax = plt.subplots()
scatter = ax.scatter(df["x"], df["y"], c=df["cluster"].cat.codes, cmap="viridis")
plt.colorbar(scatter, ax=ax, label='Cluster')
plt.show()
这给出了: