首页 > 解决方案 > Matplotlib,如何循环?

问题描述

所以我在 Matplotlib 中有这个。

plt.scatter(X[: , 0:1][Y == 0], X[: , 2:3][Y==0])
plt.scatter(X[: , 0:1][Y == 1], X[: , 2:3][Y==1])
plt.scatter(X[: , 0:1][Y == 2], X[: , 2:3][Y==2])

我想知道是否有更好的循环方式来代替:

for i in range(3):
  plt.scatter(X[: , 0:1][Y == i], X[: , 2:3][Y==i])

MVCE:

# CSV: https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv
data = np.loadtxt('/content/drive/My Drive/Colab Notebooks/Machine Learning/iris.csv', skiprows=1, delimiter=',')

X = data[:, 0:4]
Y = data[:, 4:5]

# Scatter
for i in range(len(np.intersect1d(Y, Y))):
  plt.scatter(X[: , 0:1][Y == i], X[: , 3:4][Y==i])

# map(lambda i: plt.scatter(X[: , 0:1][Y == i], X[: , 2:3][Y==i]), range(3))

plt.title("Scatter Sepal Length / Petal Width ")
plt.legend(('Setosa', 'Versicolor', 'Virginica'))
plt.show()

标签: pythonnumpyloopsmatplotlib

解决方案


显示数据的最简单方法可能是使用包含多种颜色的单个图。

关键是更有效地标记数据。你有正确的想法np.intersect1d(Y, Y),但是虽然很聪明,但这并不是设置唯一值的最佳方式。相反,我建议使用np.unique. 这不仅消除了将参数硬编码为 的需要plt.legend,而且该return_inverse参数将允许您直接构造属性。

一个小问题是您可以使用单个索引而不是切片来索引单个列。

例如,

X = np.loadtxt('iris.csv', skiprows=1, delimiter=',', usecols=[0, 1, 2, 3])
Y = np.loadtxt('iris.csv', skiprows=1, delimiter=',', usecols=[4], dtype=str)

labels, indices = np.unique(Y, return_inverse=True)
scatter = plt.scatter(X[:, 0], X[:, 2], color=indices)

数组indices索引到三个唯一值labels以获取原始数组。因此,您可以提供索引作为每个元素的标签。

为这样的标记数据集构建图例是 matplotlib 开箱即用的完全支持,正如我从matplotlib add legend with multiple entries for a single scatter plot中学到的,这是受此解决方案的启发。它的要点是plt.scatter返回的对象有一个legend_elements为你完成所有工作的方法:

plt.legend(scatter.legend_elements()[0], labels)

legend_elements返回一个包含两个项目的元组。第一个是具有不同标签的元素集合的句柄,可以用作 的第一个参数legend。第二个是一组基于您提供的数字标签的默认文本标签。我们丢弃这些以支持我们的实际文本标签。


推荐阅读