2012-03-27 76 views
1

我有一個名爲funcPower3的函數,其正文如下所示。我想用MatplotLib中的三維繪圖函數繪製該函數。我看到一個關於meshgrid的scipy文檔的例子。然而,在這個例子中,功能不定義的功能,但一個簡單的數學運算:python matplotlib - 使用meshgrid爲用戶定義的函數進行格式化

fig = plt.figure() 
ax = fig.gca(projection='3d') 
X = np.arange(-5, 5, 0.25) 
Y = np.arange(-5, 5, 0.25) 
X, Y = np.meshgrid(X, Y) 
R = np.sqrt(X**2 + Y**2) 
Z = np.sin(R) 
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet, 
    linewidth=0, antialiased=False) 

我的靈感在此示例中,但我自己的函數簽名不出來meshgrid的數據兼容。我有這樣的錯誤:

ValueError: zero-size array to minimum.reduce without identity 

我的函數的代碼是在這裏:

def funcPower3(PARAM): 
    inputX1 = open("power3X.txt","r") 
    inputY = open("power3Y.txt","r") 
    X1=[] 
    Y=[] 
    for line in inputX1: 
     X1.append(float(line)) 
    for line in inputY: 
     Y.append(float(line)) 
    resTmp_ = 0 
    res = 0 
    for i in range(len(X1)): 
     resTmp_ = Y[i] - (PARAM[0]*(X1[i])**float(PARAM[1])) 
     res += resTmp_**2 
    return res 

和代碼來繪製3D這個功能是在這裏:

XMIN = 0 YMIN = 0 XMAX = 10 ymax = 1

fig = plt.figure('Power 3') 
ax = fig.gca(projection='3d') 
Z = [] 
Xpl = numpy.arange(xmin, xmax, 0.1).tolist() 
Ypl = numpy.arange(ymin, ymax, 0.01).tolist() 
Xpl, Ypl = numpy.meshgrid(Xpl, Ypl) 
Z=[] 
for i in range(len(Xpl[0])): 
    for j in range(len(Xpl)): 
     Z.append(funcPower3([Xpl[j][i],Ypl[j][i]])) 
surf=ax.plot_surface(Xpl, Ypl, Z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet) 
ax.set_xlabel('X Label') 
ax.set_ylabel('Y Label') 
plt.show() 

謝謝並且會提出任何建議; ))

回答

4

plot_surfacedocumentation報價:

X, Y, Z : Data values as 2D arrays

但你Z是一維的。您需要重新調整它以匹配XY值。這應該工作:

Xpl = numpy.arange(xmin, xmax, 0.1).tolist() 
Ypl = numpy.arange(ymin, ymax, 0.01).tolist() 
Xpl, Ypl = numpy.meshgrid(Xpl, Ypl) 

Z=[] 
for j in range(len(Xpl)): 
    for i in range(len(Xpl[0])): 
     # your loop order was backwards 
     Z.append(funcPower3([Xpl[j][i],Ypl[j][i]])) 

# reshape Z 
Z = numpy.array(Z).reshape(Xpl.shape) 

fig = plt.figure('Power 3') 
ax = fig.gca(projection='3d') 
surf=ax.plot_surface(Xpl, Ypl, Z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet) 
ax.set_xlabel('X Label') 
ax.set_ylabel('Y Label') 
plt.show() 

但是你的代碼有一些缺陷。首先,看看你的funcPower3函數,你爲每個函數調用反覆讀取兩個文件。這太浪費了。改爲只讀一次這些參數,並將它們作爲參數提供給您的函數。這個功能也可以簡化一點(和嘗試按照PEP8命名慣例):

def func_power_3(param, x1, y): 
    p1, p2 = param 
    res = sum(y_i - (p1*x1_i)**p2 for x1_i, y_i in zip(x1, y)) 
    return res 

,其餘的將是

with open("power3X.txt","r") as infile: 
    x1 = [float(line) for line in infile] 

with open("power3Y.txt","r") as infile: 
    y = [float(line) for line in infile] 

xpl = numpy.arange(xmin, xmax, 0.1) # no need for .tolist() 
ypl = numpy.arange(ymin, ymax, 0.01) # meshgrid can work with numpy.array's 
xpl, ypl = numpy.meshgrid(xpl, ypl) 

# we can form z with list comprehension 
z = [[func_power_3([p1,p2], x1, y) for p1, p2 in zip(p1row, p2row)] 
            for p1row, p2row in zip(xpl, ypl)] 

fig = plt.figure('Power 3') 
ax = fig.gca(projection='3d') 
surf=ax.plot_surface(xpl, ypl, z, rstride=8, cstride=8, alpha=0.3,cmap=cm.jet) 
ax.set_xlabel('X Label') 
ax.set_ylabel('Y Label') 
plt.show() 
+0

這看起來非常有前途和代碼是超清晰。我有一個小問題,這個錯誤:「打開(打開(」power3X.txt「,」r「))infile: TypeError:脅迫Unicode:需要字符串或緩衝區,找到文件」 – octoback 2012-03-27 20:37:53

+0

@dlib:oops太很多「開放」:)。現在修好。 – Avaris 2012-03-27 20:38:57

+0

修正爲打開(「power3Y.txt」,「r」)爲infile: y = [float(line)for line in infile],效果很好! – octoback 2012-03-27 20:47:36

相關問題