如何使用 matplotlib 使标记方块成为精确的方块?
How do you get the marker squares to be exact squares with matplotlib?
首先,重要的是我使用 plt.scatter 而不是迭代点(补丁),因为我的真实数据有大量数据点。问题是关于如何用 plt.scatter 解决这个问题并找到正确的标记大小。
通过这个小例子,我想实现以下目标:
- 对于我的 16 个数据点中的每一个,图片上的一个正方形应该用特定于该点的颜色绘制。
- 根据图形大小,我需要计算出标记所需的确切数据点数。
我的策略:
a) 使用 ax.transData.transform 获取 0,0, 0,1, 0,2 的像素值
和 1,0, 2,0, 3,0 以验证距离是否相等。
b) 将宽度乘以高度以获得我需要的标记的大小。
c) 从像素转换为点。
d) 将此标记提供给 plt.scatter.
import numpy as np
import matplotlib.pyplot as plt
xdim = 4
figs = 5
dpi = 100
fig = plt.figure(num=None, figsize=(figs, figs), dpi=dpi, facecolor='w', edgecolor='k')
plt.xlim((-1,5))
plt.ylim((-1,5))
ax = fig.add_subplot(111)
x = np.arange(0+.5, xdim+.5, 1)
y = np.arange(0+.5, xdim+.5, 1)
X, Y = np.meshgrid(x, y)
Z= np.random.rand(xdim*xdim,3)
x_diff = np.diff(ax.transData.transform([(0,0),(0,1),(0,2),(0,3),(0,4)]),axis=0)
y_diff = np.diff(ax.transData.transform([(0,0),(1,0),(2,0),(3,0),(4,0)]),axis=0)
print(x_diff,y_diff)
x_avg = np.average(x_diff[0,1])
y_avg = np.average(y_diff[1,0])
print(x_avg,y_avg)
marker_pixels = x_avg*y_avg
marker_points = (marker_pixels*72)/dpi
print marker_points
plt.scatter(X,Y,c=Z, s=marker_points, marker='s', edgecolors=None)
plt.savefig('foo.png', dpi=dpi)
但是,在这个例子中我得到的结果是 66.666(事实!)和 64.58,即不是正方形。当我将两者相乘、转换并输入 plt.scatter 时,我得到了这张图片:
如你所见,正方形不是正方形,不要完全填满从0,0到1,1等的正方形。如果你使用fig.show(),这会更清楚看看。
这个近似解是可以的,因为格子很大看起来不错,但我想知道如何才能准确地解决这个问题。我怎样才能确保标记准确地放置在它应该适合的正方形内,从左下角正方形的两个轴上的 0,1 开始填充?
一般的答案可能是补丁,而不是标记方块,无论它有多慢。但是,使用您显示的示例的网格性质,有一种更简单的方法,您仍然可以在其上进行其他绘图:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy.random as nr
quilt = nr.random((4,4))
plt.imshow(quilt, interpolation='none', aspect='equal', cmap=cm.jet)
plt.scatter([1,2,3],[3,0,1])
plt.plot([0,1,1.4, 2.3, 3.5],[0,1,2,3,2])
plt.show()
您可以更改轴刻度以表示您的数据单位,自定义颜色图以具有缺失数据的透明方块,将 imshow 作为子图嵌入另一个图中,等等。
首先,重要的是我使用 plt.scatter 而不是迭代点(补丁),因为我的真实数据有大量数据点。问题是关于如何用 plt.scatter 解决这个问题并找到正确的标记大小。
通过这个小例子,我想实现以下目标:
- 对于我的 16 个数据点中的每一个,图片上的一个正方形应该用特定于该点的颜色绘制。
- 根据图形大小,我需要计算出标记所需的确切数据点数。
我的策略: a) 使用 ax.transData.transform 获取 0,0, 0,1, 0,2 的像素值 和 1,0, 2,0, 3,0 以验证距离是否相等。 b) 将宽度乘以高度以获得我需要的标记的大小。 c) 从像素转换为点。 d) 将此标记提供给 plt.scatter.
import numpy as np
import matplotlib.pyplot as plt
xdim = 4
figs = 5
dpi = 100
fig = plt.figure(num=None, figsize=(figs, figs), dpi=dpi, facecolor='w', edgecolor='k')
plt.xlim((-1,5))
plt.ylim((-1,5))
ax = fig.add_subplot(111)
x = np.arange(0+.5, xdim+.5, 1)
y = np.arange(0+.5, xdim+.5, 1)
X, Y = np.meshgrid(x, y)
Z= np.random.rand(xdim*xdim,3)
x_diff = np.diff(ax.transData.transform([(0,0),(0,1),(0,2),(0,3),(0,4)]),axis=0)
y_diff = np.diff(ax.transData.transform([(0,0),(1,0),(2,0),(3,0),(4,0)]),axis=0)
print(x_diff,y_diff)
x_avg = np.average(x_diff[0,1])
y_avg = np.average(y_diff[1,0])
print(x_avg,y_avg)
marker_pixels = x_avg*y_avg
marker_points = (marker_pixels*72)/dpi
print marker_points
plt.scatter(X,Y,c=Z, s=marker_points, marker='s', edgecolors=None)
plt.savefig('foo.png', dpi=dpi)
但是,在这个例子中我得到的结果是 66.666(事实!)和 64.58,即不是正方形。当我将两者相乘、转换并输入 plt.scatter 时,我得到了这张图片:
如你所见,正方形不是正方形,不要完全填满从0,0到1,1等的正方形。如果你使用fig.show(),这会更清楚看看。
这个近似解是可以的,因为格子很大看起来不错,但我想知道如何才能准确地解决这个问题。我怎样才能确保标记准确地放置在它应该适合的正方形内,从左下角正方形的两个轴上的 0,1 开始填充?
一般的答案可能是补丁,而不是标记方块,无论它有多慢。但是,使用您显示的示例的网格性质,有一种更简单的方法,您仍然可以在其上进行其他绘图:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy.random as nr
quilt = nr.random((4,4))
plt.imshow(quilt, interpolation='none', aspect='equal', cmap=cm.jet)
plt.scatter([1,2,3],[3,0,1])
plt.plot([0,1,1.4, 2.3, 3.5],[0,1,2,3,2])
plt.show()
您可以更改轴刻度以表示您的数据单位,自定义颜色图以具有缺失数据的透明方块,将 imshow 作为子图嵌入另一个图中,等等。