[英]Python for-loop always plots the same line when 3D (using matplotlib)
我在 Python 中使用 matplotlib 在同一個圖形上繪制多條線,方法是使用 for 循環將每條線添加到軸上。
當以 2D 方式繪制時,每條線都在另一條線上,這很好用。
但是,在 3D 中繪圖時,每次我運行 for 循環時,python 都會顯示相同的圖形數據,即使數據明顯不同。
編輯:我不認為這個問題是“ 我如何判斷 NumPy 創建視圖還是副本? ”的重復,因為它突出了意外行為的一個特定實例。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
###### Unimportant maths not relevant to the question ######
def rossler(x_n, y_n, z_n, h, a, b, c):
#defining the rossler function
x_n1=x_n+h*(-y_n-z_n)
y_n1=y_n+h*(x_n+a*y_n)
z_n1=z_n+h*(b+z_n*(x_n-c))
return x_n1,y_n1,z_n1
#defining a, b, and c
a = 1.0/5.0
b = 1.0/5.0
c = 5
#defining time limits and steps
t_0 = 0
t_f = 50*np.pi
h = 0.01
steps = int((t_f-t_0)/h)
#create plotting values
t = np.linspace(t_0,t_f,steps)
x = np.zeros(steps)
y = np.zeros(steps)
z = np.zeros(steps)
##### Relevant to the question again #####
init_condition_array = [[0,0,0],[0.1,0,0],[0.2,0,0],[0.3,0,0]]
color_array = ["red","orange","green","blue"]
color_counter = 0
zs_array = [0, 0.1, 0.2, 0.3]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for row in init_condition_array:
x[0] = row[0]
y[0] = row[1]
z[0] = row[2]
for i in range(x.size-1):
#re-evaluate the values of the x-arrays depending on the initial conditions
[x[i+1],y[i+1],z[i+1]]=rossler(x[i],y[i],z[i],t[i+1]-t[i],a,b,c)
plt.plot(t,x,zs=zs_array[color_counter],zdir="z",color=color_array[color_counter])
color_counter += 1
ax.set_xlabel('t')
ax.set_ylabel('x(t)')
plt.show()
如您所見,圖表看起來應該大不相同;
這是同一軸上圖形的二維圖像,對代碼進行了一些改動(如下所示):
雖然這是 3D 繪圖生成的圖形:
.
二維圖是通過對代碼進行這些小改動而創建的; 第一行以上沒有任何改變:
init_condition_array = [[0,0,0],[0.1,0,0],[0.2,0,0],[0.3,0,0]]
color_array = ["red","orange","green","blue"]
color_counter = 0
fig = plt.figure()
ax = fig.add_subplot(111)
for row in init_condition_array:
x[0] = row[0]
y[0] = row[1]
z[0] = row[2]
for i in range(x.size-1):
#re-evaluate the values of the x-arrays depending on the initial conditions
[x[i+1],y[i+1],z[i+1]]=rossler(x[i],y[i],z[i],t[i+1]-t[i],a,b,c)
plt.plot(t,x,color=color_array[color_counter],lw=1)
color_counter += 1
ax.set_xlabel('t')
ax.set_ylabel('x(t)')
plt.show()
for row in init_condition_array
循環中的for row in init_condition_array
內移動x = np.zeros(steps)
修復/避免了該問題。 x
被存儲在內部Line3D
對象通過返回plt.plot
,和變異x
影響存儲在其它值Line3Ds
。
如果您跟蹤通過源代碼Line3D
你會發現,你傳遞給數據plt.plot
在結束了Line3D
的_verts3d
屬性。 數據不被復制; _verts3d
元組包含對完全相同數組的引用。
而這個_verts3d
屬性是在后面渲染的時候直接訪問的:
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
因此改變數據——即使在調用plt.plot
之后——也會改變self._verts3d
。 這個簡單的例子演示了這個問題:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
t = np.linspace(0, 1, 5)
x = np.sin(t)
line, = plt.plot(t, x, 0)
這里我們有x
的原始值:
print(line._verts3d[1])
# [ 0. 0.24740396 0.47942554 0.68163876 0.84147098]
這表明變異x
修改line._verts3d
:
x[:] = 1
print(line._verts3d[1])
# [ 1. 1. 1. 1. 1.]
# The result is a straight line, not a sine wave.
plt.show()
制作 2D 線圖時不會發生這種令人驚訝的陷阱,因為保存用於渲染的數據的Line2D._xy
屬性存儲了原始數據的副本。
這個問題可以在源代碼中通過改變art3d.Line3D.set_3d_properties
這一行來art3d.Line3D.set_3d_properties
self._verts3d = art3d.juggle_axes(xs, ys, zs, zdir)
到
import copy
self._verts3d = copy.deepcopy(art3d.juggle_axes(xs, ys, zs, zdir))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.