Python matplotlib - 使用meshgrid格式化用户定义的函数

时间:2012-03-27 19:17:17

标签: python plot matplotlib scipy

我有一个名为funcPower3的函数,正文如下所示。我想在MatplotLib中使用3D绘图功能绘制此函数。我在使用meshgrid的scipy docs上看到了一个例子。但是,在此示例中,函数不是已定义的函数,而是简单的数学运算:

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

感谢和问候任何建议; ))

1 个答案:

答案 0 :(得分:4)

引自plot_surface documentation

  

X,Y,Z:数据值为2D数组

但是你的Z是1维的。您需要对其进行重新整形以匹配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()