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

kir*_*off 1 python plot matplotlib scipy

我有一个名为 funcPower3 的函数,其主体如下所示。我想在 MatplotLib 中使用 3D 绘图功能绘制此函数。我在带有网格网格的 scipy 文档中看到了一个示例。然而,在这个例子中,function 不是一个定义的函数,而是一个简单的数学运算:

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)
Run Code Online (Sandbox Code Playgroud)

我从这个示例中汲取了灵感,但我自己的函数签名与来自网格网格的数据不兼容。我有这个错误:

 ValueError: zero-size array to minimum.reduce without identity
Run Code Online (Sandbox Code Playgroud)

我的函数代码在这里:

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
Run Code Online (Sandbox Code Playgroud)

绘制 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()
Run Code Online (Sandbox Code Playgroud)

感谢并问候您的任何建议;))

Ava*_*ris 6

引用自plot_surface 文档

X, Y, Z : 二维数组形式的数据值

但你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()
Run Code Online (Sandbox Code Playgroud)

但是你的代码有几个缺陷。首先,查看您的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
Run Code Online (Sandbox Code Playgroud)

剩下的就是

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()
Run Code Online (Sandbox Code Playgroud)