Python 使用调色板进行散点图时显示正确的图例 绘制散点图的愚蠢方法

Python 使用调色板进行散点图时显示正确的图例 绘制散点图的愚蠢方法,python,python-3.x,matplotlib,Python,Python 3.x,Matplotlib,假设我有一个包含3个类的数据,下面的代码可以为我提供一个带有正确图例的完美图形,其中我按类绘制数据 import matplotlib.pyplot as plt import seaborn as sns from sklearn.datasets import make_blobs import numpy as np X, y = make_blobs() X0 = X[y==0] X1 = X[y==1] X2 = X[y==2] ax = plt.subplot(1,1,1) a

假设我有一个包含3个类的数据,下面的代码可以为我提供一个带有正确图例的完美图形,其中我按类绘制数据

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs()

X0 = X[y==0]
X1 = X[y==1]
X2 = X[y==2]

ax = plt.subplot(1,1,1)
ax.scatter(X0[:,0],X0[:,1], lw=0, s=40)
ax.scatter(X1[:,0],X1[:,1], lw=0, s=40)
ax.scatter(X2[:,0],X2[:,1], lw=0, s=40)
ax.legend(['0','1','2'])

绘制散点图的更好方法 但是,如果我有一个包含3000个类的数据集,那么上面的方法就不再有效了。(你不会希望我为每个类写3000行,对吧?) 所以我想出了下面的绘图代码

num_classes = len(set(y))
palette = np.array(sns.color_palette("hls", num_classes))

ax = plt.subplot(1,1,1)
ax.scatter(X[:,0], X[:,1], lw=0, s=40, c=palette[y.astype(np.int)])
ax.legend(['0','1','2'])

这段代码非常完美,我们可以用一行代码画出所有的类。但是,这次图例显示不正确

问题: 当我们使用以下方法绘制图形时,如何保持正确的图例

ax.scatter(X[:,0], X[:,1], lw=0, s=40, c=palette[y.astype(np.int)])
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs()
ngroups = 3

ax = plt.subplot(1, 1, 1)
for i in range(ngroups):
    ax.scatter(X[y==i][:,0], X[y==i][:,1], lw=0, s=40, label=i)
ax.legend()
plt.legend()
在绘图上有多个“艺术家”时效果最佳。第一个示例就是这样,这就是调用
plt.legend(labels)
可以轻松工作的原因

如果您担心编写大量代码行,那么可以利用
for
循环

正如我们在本例中使用5个类所看到的:

import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs(centers=5)
ax = plt.subplot(1,1,1)

for c in np.unique(y):
    ax.scatter(X[y==c,0],X[y==c,1],label=c)

ax.legend()

np.unique()
返回y的唯一元素的排序数组,通过循环这些元素并用自己的艺术家绘制每个类
plt.legend()
可以轻松提供图例

编辑: 您还可以在绘制图时为其指定标签,这可能更安全

plt.scatter(…,label=c)
后接
plt.legend()
plt.legend()
在绘图上有多个“艺术家”时效果最佳。第一个示例就是这样,这就是调用
plt.legend(labels)
可以轻松工作的原因

如果您担心编写大量代码行,那么可以利用
for
循环

正如我们在本例中使用5个类所看到的:

import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs(centers=5)
ax = plt.subplot(1,1,1)

for c in np.unique(y):
    ax.scatter(X[y==c,0],X[y==c,1],label=c)

ax.legend()

np.unique()
返回y的唯一元素的排序数组,通过循环这些元素并用自己的艺术家绘制每个类
plt.legend()
可以轻松提供图例

编辑: 您还可以在绘制图时为其指定标签,这可能更安全


plt.scatter(…,label=c)
后跟
plt.legend()
为什么不简单地执行以下操作

ax.scatter(X[:,0], X[:,1], lw=0, s=40, c=palette[y.astype(np.int)])
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs()
ngroups = 3

ax = plt.subplot(1, 1, 1)
for i in range(ngroups):
    ax.scatter(X[y==i][:,0], X[y==i][:,1], lw=0, s=40, label=i)
ax.legend()

为什么不简单地做下面的事情呢

ax.scatter(X[:,0], X[:,1], lw=0, s=40, c=palette[y.astype(np.int)])
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_blobs
import numpy as np

X, y = make_blobs()
ngroups = 3

ax = plt.subplot(1, 1, 1)
for i in range(ngroups):
    ax.scatter(X[y==i][:,0], X[y==i][:,1], lw=0, s=40, label=i)
ax.legend()

我认为Matplotlib的散点图从来没有打算按颜色、宽度或大小进行分组:后一种选择是传递额外的信息,实际上是第三或第四轴,而不是按数据分组。相反,您应该在数据集上循环,创建单独的散点图。使用数组或dict分配子组,或者实际上不分配子组,但在循环条件时立即绘制它们。如果数据集包含3000个类(或者超过20个类),标签和可读性方面的问题与必须写3000行几乎相同的行不同。我认为Matplotlib的散点图从来没有打算按颜色、宽度或大小进行分组:后一种选择是传递附加信息,实际上是第三轴或第四轴,而不是按第三轴或第四轴对数据进行分组。相反,您应该在数据集上循环,创建单独的散点图。使用数组或dict分配子组,或者实际上不分配子组,但在循环条件时立即绘制它们。如果数据集包含3000个类(或者超过20个类),您在标签和可读性方面遇到的问题与必须在接近相同的行上书写3000条不同。因为为大量点创建单个散点图比创建多个散点图更有效。@重要的是它吗?这是如何衡量的?我必须说,我发现在第二个副本的公认答案中使用绘制空数组来创建句柄有点尴尬,而简单的循环更简单。谢谢你的提问。这让我意识到,当用单一颜色绘制散射时,有一个优化在起作用。因此,如果总散射点的数量非常大,则循环中单个颜色的少量散射确实比具有多种颜色的单个散射更有效。更有效的方法是使用
散点图
而不是
散点图
。因为为大量点创建单个散点图比创建多个散点图更有效。@ImportanceOfBeingErnest?这是如何衡量的?我必须说,我发现在第二个副本的公认答案中使用绘制空数组来创建句柄有点尴尬,而简单的循环更简单。谢谢你的提问。这让我意识到,当用单一颜色绘制散射时,有一个优化在起作用。因此,如果总散射点的数量非常大,则循环中单个颜色的少量散射确实比具有多种颜色的单个散射更有效。更有效的方法是使用
绘图
而不是
散点