I believe a similar question to this was asked before, but it didn't really clarify things for me.
Basically, I have a list of tuples, each of which functions as a point (so (x, y, z) for example).
I want to plot them in either 2D or 3D after I run a clustering algorithm (that color codes the points).
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"
Cluster 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 plots work just fine (and look really nice), but 3D plots give me a warning:
UserWarning: No labeled objects found. Use label='...' kwarg on individual plots.
warnings.warn("No labeled objects found. "
And no legend appears. But I am labeling the points, and the code I am using is almost identical, so I am confused as to what the problem is. I heard something about a proxy object, but I have no clue how to use that for this case.
I partially solved my problem by adding the following code:
ax.plot([], [], 'o', c=self.clusters[i].color, label="Cluster " + str(i + 1))
to each iteration of the loop, giving the following figure.
The marker is doubled for some reason, but at least it mostly works. If someone can comment on why it is doubled that would be great.
Edit Per jedwards comment, I fixed it by changing my legend() call to:
plt.legend(numpoints=1 , loc='upper left')
I'm not sure what the format of your self.clusters
is, but with something I came up with that I think closely resembles it, I was able to produce the following:
With the code
for i,c in enumerate(self.clusters):
x,y,z = c.points
ax.text(x,y,z, "Cluster %d" % (i+1), None)
Based off text3d demo .
I'm using matplotlib 1.4.3
Note , you won't be able to "drag and drop" this code, since my cluster instances are simple 3-tuples, yours seem more complicated.
I may not fully understood your question, but here is an example you may tweak it to your case. Hope it helps:
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()
It produces this:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.