Seaborn散点图矩阵 - 使用自定义样式添加额外点

arf*_*fon 5 matplotlib seaborn

我正在对GitHub上的一些开源项目进行k-means聚类活动,并尝试使用Seaborn Scatterplot Matrix将结果与聚类质心一起绘制.

我可以成功绘制聚类分析的结果(示例下面的tsv输出)

user_id issue_comments  issues_created  pull_request_review_comments    pull_requests   category
1   0.14936519790888722 2.0100502512562812  0.0 0.60790273556231    Group 0
1882    0.11202389843166542 0.5025125628140703  0.0 0.0 Group 1
2   2.315160567587752   20.603015075376884  0.13297872340425532 1.21580547112462    Group 2
1789    36.8185212845407    82.91457286432161   75.66489361702128   74.46808510638297   Group 3
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我也希望能够在矩阵图上绘制聚类的质心.目前我的绘图脚本如下所示:

import seaborn as sns
import pandas as pd
from pylab import savefig
sns.set()

# By default, Pandas assumes the first column is an index
# so it will be skipped. In our case it's the user_id
data = pd.DataFrame.from_csv('summary_clusters.tsv', sep='\t')

grid = sns.pairplot(data, hue="category", diag_kind="kde")
savefig('normalised_clusters.png', dpi = 150)
Run Code Online (Sandbox Code Playgroud)

这会产生预期的输出: 矩阵图

我希望能够在每个图上标记簇的质心.我可以想到两种方法:

  1. 创建一个新的"CENTROID"类别,并将其与其他点一起绘制.
  2. 调用后手动为绘图添加额外的点数sns.pairplot(data, hue="category", diag_kind="kde").

如果(1)是解决方案,那么我希望能够自定义标记(可能是一个星?)以使其更加突出.

如果(2)我全都耳朵.我对Seaborn和Matplotlib很新,所以非常欢迎任何帮助:-)

mwa*_*kom 8

pairplot并不是那么适合这种事情,但它可以使它有一些技巧.这就是我要做的.

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
sns.set_color_codes()

# Make some random iid data
cov = np.eye(3)
ds = np.vstack([np.random.multivariate_normal([0, 0, 0], cov, 50),
                np.random.multivariate_normal([1, 1, 1], cov, 50)])
ds = pd.DataFrame(ds, columns=["x", "y", "z"])

# Fit the k means model and label the observations
km = KMeans(2).fit(ds)
ds["label"] = km.labels_.astype(str)
Run Code Online (Sandbox Code Playgroud)

现在出现了非显而易见的部分:您需要创建一个带有质心位置的数据框,然后将其与观察数据框结合起来,同时使用该label列识别质心:

centroids = pd.DataFrame(km.cluster_centers_, columns=["x", "y", "z"])
centroids["label"] = ["0 centroid", "1 centroid"]
full_ds = pd.concat([ds, centroids], ignore_index=True)
Run Code Online (Sandbox Code Playgroud)

然后你只需要使用PairGrid,它比它更灵活,pairplot并允许你通过色调变量和颜色映射其他绘图属性(代价是无法在对角线上绘制直方图):

g = sns.PairGrid(full_ds, hue="label",
                 hue_order=["0", "1", "0 centroid", "1 centroid"],
                 palette=["b", "r", "b", "r"],
                 hue_kws={"s": [20, 20, 500, 500],
                          "marker": ["o", "o", "*", "*"]})
g.map(plt.scatter, linewidth=1, edgecolor="w")
g.add_legend()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

另一种解决方案是将观察结果绘制为正常,然后更改PairGrid对象上的数据属性并添加新图层.我称之为黑客,但在某些方面它更直接.

# Plot the data
g = sns.pairplot(ds, hue="label", vars=["x", "y", "z"], palette=["b", "r"])

# Change the PairGrid dataset and add a new layer
centroids = pd.DataFrame(km.cluster_centers_, columns=["x", "y", "z"])
g.data = centroids
g.hue_vals = [0, 1]
g.map_offdiag(plt.scatter, s=500, marker="*")
Run Code Online (Sandbox Code Playgroud)