Matplotlib:3D 散点图无法识别标签
Matplotlib: 3D Scatter plots not recognizing labels
我相信之前有人问过与此类似的问题,但它并没有真正为我澄清问题。
基本上,我有一个元组列表,每个元组都充当一个点(例如 (x, y, z))。
我想在 运行 聚类算法(对点进行颜色编码)后以 2D 或 3D 方式绘制它们。
clusters = []
def plotPoints(self):
fig = plt.figure()
if self.clusters[0].dimensions == 2:
ax = fig.add_subplot(111)
for i in range(0, len(self.clusters)):
ax.scatter(*zip(*self.clusters[i].points), c=self.clusters[i].color, marker="o", label=("Cluster " + str(i + 1)))
plt.legend(loc='upper left')
plt.show()
elif self.clusters[0].dimensions == 3:
ax = fig.add_subplot(111, projection='3d')
for i in range(0, len(self.clusters)):
ax.scatter(*zip(*self.clusters[i].points), c=self.clusters[i].color, marker="o", label=("Cluster " + str(i + 1)))
plt.legend(loc='upper left')
plt.show()
else:
print "Cannot plot in dimensions lower than 2 or higher than 3"
集群class:
class Cluster(object):
centroid = ()
dimensions = 0
color = 'k'
def __init__(self, init_pt, color):
self.points = []
self.points.append(init_pt)
self.dimensions = len(init_pt)
self.centroid = init_pt
self.color = color
def addPoint(self, pt):
try:
if len(pt) != self.dimensions:
raise ArithmeticError("Wrong number of dimensions on new point, ignoring")
else:
centroid_dim_list = []
for dim in range(0, self.dimensions):
centroid_dim_list.append((self.centroid[dim] * len(self.points) + pt[dim]) / float(len(self.points) + 1))
self.centroid = tuple(centroid_dim_list)
self.points.append(pt)
except ArithmeticError as ae:
print ae.message
pass
2D 绘图工作得很好(而且看起来非常好),但 3D 绘图给我一个警告:
UserWarning: No labeled objects found. Use label='...' kwarg on individual plots.
warnings.warn("No labeled objects found. "
而且没有图例出现。但是我正在标记要点,并且我使用的代码几乎相同,所以我对问题出在哪里感到困惑。我听说过代理对象,但我不知道如何在这种情况下使用它。
我不确定你的 self.clusters
的格式是什么,但是我想出了一些我认为非常相似的东西,我能够产生以下内容:
用代码
for i,c in enumerate(self.clusters):
x,y,z = c.points
ax.text(x,y,z, "Cluster %d" % (i+1), None)
基于 text3d demo。
我正在使用 matplotlib 1.4.3
注意,你将无法"drag and drop"这段代码,因为我的集群实例是简单的三元组,你的看起来更复杂。
我通过添加以下代码部分解决了我的问题:
ax.plot([], [], 'o', c=self.clusters[i].color, label="Cluster " + str(i + 1))
循环的每一次迭代,给出下图。
标记由于某种原因加倍了,但至少它在大多数情况下是有效的。如果有人可以评论为什么它加倍,那就太好了。
编辑
根据 jedwards 的评论,我通过将 legend() 调用更改为:
来修复它
plt.legend(numpoints=1 , loc='upper left')
我可能没有完全理解你的问题,但这里有一个例子,你可以根据自己的情况进行调整。希望对您有所帮助:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from random import randint
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# dataset
def data():
return [randint(0,100) for _ in range(10)]
c1 = (data(), data(), data())
c2 = (data(), data(), data())
c3 = (data(), data(), data())
clusters = [c1, c2, c3]
# plot
colors = ['r', 'b', 'y', 'c']
for i, c in enumerate(clusters):
ax.scatter(c[0], c[1], c[2], c=colors[i], label='cluster {}'.format(i))
ax.legend(bbox_to_anchor = (1.5, 1))
plt.show()
它产生这个:
我相信之前有人问过与此类似的问题,但它并没有真正为我澄清问题。
基本上,我有一个元组列表,每个元组都充当一个点(例如 (x, y, z))。
我想在 运行 聚类算法(对点进行颜色编码)后以 2D 或 3D 方式绘制它们。
clusters = []
def plotPoints(self):
fig = plt.figure()
if self.clusters[0].dimensions == 2:
ax = fig.add_subplot(111)
for i in range(0, len(self.clusters)):
ax.scatter(*zip(*self.clusters[i].points), c=self.clusters[i].color, marker="o", label=("Cluster " + str(i + 1)))
plt.legend(loc='upper left')
plt.show()
elif self.clusters[0].dimensions == 3:
ax = fig.add_subplot(111, projection='3d')
for i in range(0, len(self.clusters)):
ax.scatter(*zip(*self.clusters[i].points), c=self.clusters[i].color, marker="o", label=("Cluster " + str(i + 1)))
plt.legend(loc='upper left')
plt.show()
else:
print "Cannot plot in dimensions lower than 2 or higher than 3"
集群class:
class Cluster(object):
centroid = ()
dimensions = 0
color = 'k'
def __init__(self, init_pt, color):
self.points = []
self.points.append(init_pt)
self.dimensions = len(init_pt)
self.centroid = init_pt
self.color = color
def addPoint(self, pt):
try:
if len(pt) != self.dimensions:
raise ArithmeticError("Wrong number of dimensions on new point, ignoring")
else:
centroid_dim_list = []
for dim in range(0, self.dimensions):
centroid_dim_list.append((self.centroid[dim] * len(self.points) + pt[dim]) / float(len(self.points) + 1))
self.centroid = tuple(centroid_dim_list)
self.points.append(pt)
except ArithmeticError as ae:
print ae.message
pass
2D 绘图工作得很好(而且看起来非常好),但 3D 绘图给我一个警告:
UserWarning: No labeled objects found. Use label='...' kwarg on individual plots.
warnings.warn("No labeled objects found. "
而且没有图例出现。但是我正在标记要点,并且我使用的代码几乎相同,所以我对问题出在哪里感到困惑。我听说过代理对象,但我不知道如何在这种情况下使用它。
我不确定你的 self.clusters
的格式是什么,但是我想出了一些我认为非常相似的东西,我能够产生以下内容:
用代码
for i,c in enumerate(self.clusters):
x,y,z = c.points
ax.text(x,y,z, "Cluster %d" % (i+1), None)
基于 text3d demo。
我正在使用 matplotlib 1.4.3
注意,你将无法"drag and drop"这段代码,因为我的集群实例是简单的三元组,你的看起来更复杂。
我通过添加以下代码部分解决了我的问题:
ax.plot([], [], 'o', c=self.clusters[i].color, label="Cluster " + str(i + 1))
循环的每一次迭代,给出下图。
标记由于某种原因加倍了,但至少它在大多数情况下是有效的。如果有人可以评论为什么它加倍,那就太好了。
编辑 根据 jedwards 的评论,我通过将 legend() 调用更改为:
来修复它plt.legend(numpoints=1 , loc='upper left')
我可能没有完全理解你的问题,但这里有一个例子,你可以根据自己的情况进行调整。希望对您有所帮助:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from random import randint
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# dataset
def data():
return [randint(0,100) for _ in range(10)]
c1 = (data(), data(), data())
c2 = (data(), data(), data())
c3 = (data(), data(), data())
clusters = [c1, c2, c3]
# plot
colors = ['r', 'b', 'y', 'c']
for i, c in enumerate(clusters):
ax.scatter(c[0], c[1], c[2], c=colors[i], label='cluster {}'.format(i))
ax.legend(bbox_to_anchor = (1.5, 1))
plt.show()
它产生这个: