正确使用坐标与 Plotly 绘制表面数据?
Correct use of coordinates to plot surface data with Plotly?
假设我有一个 x 值数组 X
和 y 值数组 Y
,以及一个字典 results
,以便 results[x][y]
访问 z 值。我如何构造一个 z
变量才能正确匹配生成它的坐标?
例如:
X = [0,2,3]
Y = [-1,-2,-3]
results = {x:{y: x/y for y in Y} for x in X}
Z = np.array([[results[x][y] for y in Y] for x in X ])
fig = go.Figure(data=[go.Surface(z=Z, x=X, y=Y)])
fig.update_layout(title='Plot', autosize=False,
width=500, height=500,
margin=dict(l=65, r=50, b=65, t=90))
fig.update_layout(scene = dict(xaxis_title='X',
yaxis_title='Y'
)
)
fig.show()
给出了错误的图表:
这个坐标系是怎么工作的?执行 Z = np.array([[results[x][y] for x in X] for y in Y ])
给出了正确的结果,但这对我来说没有意义。为什么x
是第二个坐标?
问题
您得到奇怪结果的原因是计算机表示矩阵的方式,即按行和列表示索引 0, 0
处的“第一个”元素位于左上角,而考虑以左下角为原点的 XY 平面更直观,这是在数学中查看图形的标准方式。
解决方案
首先,通过充分利用 numpy,您可以通过 np.divide.outer()
更快地计算 z
。这给出了 z
的正确结果,没有不必要的 dict
和嵌套理解(并且对于更大的数组会更有效)。
x = np.array([0, 2, 3])
y = np.array([-1, -2, -3])
z = np.divide.outer(x, y)
现在,由于计算机看到的矩阵与直觉上看到的 z = f(x, y)
不同,您需要绘制 z
的转置:
fig = go.Figure(data=[go.Surface(z=z.T, x=x, y=y)])
结果:
稍微详细一点的解释
如果我们调整绘图的方向,使 x 轴方向与我们通常在 2D 图形上查看它的方式相同(从左到右增加):
你可以看到在表面的左边缘,z
,所有的值都是零。但是请注意 z
是如何表示为数组的:
>>> np.round(z, 2)
array([[-0. , -0. , -0. ],
[-2. , -1. , -0.67],
[-3. , -1.5 , -1. ]])
如果转置 z
,您会看到矩阵的“左”边全为零:
>>> np.round(z.T, 2)
array([[-0. , -2. , -3. ],
[-0. , -1. , -1.5 ],
[-0. , -0.67, -1. ]])
这有望帮助阐明 xy 坐标和数组的行列表示之间的差异。还需要注意的是,在上面重新定向的图中,y 轴是“反转”的。这是因为矩阵的顶行被认为是“第一个”元素,但在正常的 xy 坐标系中,y 轴垂直增加(即从底部开始)。
对多元函数使用网格
您可以使用 np.meshgrid()
:
来避免转置 z
>>> x_coords, y_coords = np.meshgrid(x, y, indexing="xy")
>>> z = x_coords / y_coords
>>> z
array([[-0. , -2. , -3. ],
[-0. , -1. , -1.5 ],
[-0. , -0.67, -1. ]])
现在请注意,z
已经采用了正确的格式来绘制为曲面。请注意,这也摆脱了 np.outer()
的必要性。使用 meshgrid 也可以更好地评估坐标网格上的任意函数。
假设我有一个 x 值数组 X
和 y 值数组 Y
,以及一个字典 results
,以便 results[x][y]
访问 z 值。我如何构造一个 z
变量才能正确匹配生成它的坐标?
例如:
X = [0,2,3]
Y = [-1,-2,-3]
results = {x:{y: x/y for y in Y} for x in X}
Z = np.array([[results[x][y] for y in Y] for x in X ])
fig = go.Figure(data=[go.Surface(z=Z, x=X, y=Y)])
fig.update_layout(title='Plot', autosize=False,
width=500, height=500,
margin=dict(l=65, r=50, b=65, t=90))
fig.update_layout(scene = dict(xaxis_title='X',
yaxis_title='Y'
)
)
fig.show()
给出了错误的图表:
这个坐标系是怎么工作的?执行 Z = np.array([[results[x][y] for x in X] for y in Y ])
给出了正确的结果,但这对我来说没有意义。为什么x
是第二个坐标?
问题
您得到奇怪结果的原因是计算机表示矩阵的方式,即按行和列表示索引 0, 0
处的“第一个”元素位于左上角,而考虑以左下角为原点的 XY 平面更直观,这是在数学中查看图形的标准方式。
解决方案
首先,通过充分利用 numpy,您可以通过 np.divide.outer()
更快地计算 z
。这给出了 z
的正确结果,没有不必要的 dict
和嵌套理解(并且对于更大的数组会更有效)。
x = np.array([0, 2, 3])
y = np.array([-1, -2, -3])
z = np.divide.outer(x, y)
现在,由于计算机看到的矩阵与直觉上看到的 z = f(x, y)
不同,您需要绘制 z
的转置:
fig = go.Figure(data=[go.Surface(z=z.T, x=x, y=y)])
结果:
稍微详细一点的解释
如果我们调整绘图的方向,使 x 轴方向与我们通常在 2D 图形上查看它的方式相同(从左到右增加):
你可以看到在表面的左边缘,z
,所有的值都是零。但是请注意 z
是如何表示为数组的:
>>> np.round(z, 2)
array([[-0. , -0. , -0. ],
[-2. , -1. , -0.67],
[-3. , -1.5 , -1. ]])
如果转置 z
,您会看到矩阵的“左”边全为零:
>>> np.round(z.T, 2)
array([[-0. , -2. , -3. ],
[-0. , -1. , -1.5 ],
[-0. , -0.67, -1. ]])
这有望帮助阐明 xy 坐标和数组的行列表示之间的差异。还需要注意的是,在上面重新定向的图中,y 轴是“反转”的。这是因为矩阵的顶行被认为是“第一个”元素,但在正常的 xy 坐标系中,y 轴垂直增加(即从底部开始)。
对多元函数使用网格
您可以使用 np.meshgrid()
:
z
>>> x_coords, y_coords = np.meshgrid(x, y, indexing="xy")
>>> z = x_coords / y_coords
>>> z
array([[-0. , -2. , -3. ],
[-0. , -1. , -1.5 ],
[-0. , -0.67, -1. ]])
现在请注意,z
已经采用了正确的格式来绘制为曲面。请注意,这也摆脱了 np.outer()
的必要性。使用 meshgrid 也可以更好地评估坐标网格上的任意函数。