2016-04-01 93 views
2

我在同一個圖上使用matplotlib在Python中繪製多條線,方法是使用for-loop將每條線添加到軸。Python for-loop總是繪製3D時的同一條線(使用matplotlib)

當用2D繪製每條線在另一條線上時,這工作正常。

然而,當繪製3D圖時,即使數據顯着不同,python每次運行for循環時都會顯示相同的圖形數據。

編輯:我不認爲這個問題是「How can I tell if NumPy creates a view or a copy?」的重複,因爲它突出了一個意外行爲的特定實例。

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() 

正如你所看到的,這些圖應該看起來非常不同;

這是在同一軸線上的曲線與一些改變的對代碼的2D圖像(如下所示):

雖然這是由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() 
+3

移動'X = np.zeros(步驟)'內被固定在源代碼中的' for init_condition_array'循環修復/避免了這個問題。它出現(不知何故)'x'存儲在由'plt.plot'返回的'Line3D'對象內,但突變'x'影響存儲在其他'Line3D'中的值... – unutbu

+1

可能有[可以重複我告訴NumPy是否創建視圖或副本?](http://stackoverflow.com/questions/11524664/how-can-i-tell-if-numpy-creates-a-view-or-a-copy) –

+0

謝謝@unutbu;這是排序它 - 有趣的是,我有興趣看到那個文件。 –

回答

1

移動x = np.zeros(steps)for row in init_condition_array循環修復內部/可以避免這個問題。 x存儲在由plt.plot返回的Line3D對象內,並且突變x影響存儲在其他Line3Ds中的值。

enter image description here


如果跟蹤通過source code for 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() 

這令人驚訝在製作二維線條圖時不會發生錯誤,因爲保存用於渲染的數據的Line2D._xy屬性存儲原始數據的副本。


這個問題可以通過從

self._verts3d = art3d.juggle_axes(xs, ys, zs, zdir) 

art3d.Line3D.set_3d_properties改變this line

import copy 
self._verts3d = copy.deepcopy(art3d.juggle_axes(xs, ys, zs, zdir)) 
相關問題