如何绘制 2 个变量的 3D 函数图

问题描述 投票:0回答:4

我正在尝试以 3D 方式绘制多种阻尼类型的振动放大系数。为了让那些不知道它是什么的人简化一下,基本上,你有 3 个变量:

  • beta,在 0 和无限之间变化,但我想以 0.2 的间隔将其可视化为 0 到 3。
  • 阻尼比 d,在 0 和无穷大之间变化,但我想以 0.1 的间隔将其从 0 到 1 绘制。
  • 最后是nu,它是一个根据之前两个变量而变化的函数。

我的直觉告诉我应该用 (X,Y,Z) = (beta, d, nu) 来绘制它,但我刚刚开始使用这个库,而且我对 python 有点陌生,我只是在我使用它的时候使用它需要在课堂上想象或计算问题。我尝试为 beta 和 d 创建 2 个数组,但我不知道应该为 nu 创建数组,因为它依赖于两者。

这是我到目前为止的代码:

    import math
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


nu = []
b = [0.1 + i / 100 for i in range(0, 510)]
damp = [0.1 + i/10 for i in range(0,510)]

for d in damp:
    nu_new = []
    nu.append(nu_new)
    for beta in b:
        nu_new.append( math.sqrt(1+(2*d*beta)**2)/ math.sqrt((1-beta**2)**2+(2*d*beta)**2))

fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

我有点被困在试图绘制这个,所以如果你有任何建议,我会很高兴。

python matplotlib matplotlib-3d
4个回答
14
投票

如果您使用

numpy
,则不要使用
math
模块。 Numpy 作为内置的所有数学函数,但它们在 numpy 数组上的工作效果要好得多。我们可以借助网格计算所有 b、d 值的 nu。

网格网格可以接受 2 个 1D 数组,并返回 2 个 2D 数组,使得数组中的每个索引对应于原始 1D 数组中唯一的一对元素。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

b = np.arange(0.2, 3.2, 0.2)
d = np.arange(0.1, 1.0, 0.1)

B, D = np.meshgrid(b, d)
nu = np.sqrt( 1 + (2*D*B)**2 ) / np.sqrt( (1-B**2)**2 + (2*D*B)**2)

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(B, D, nu)
plt.xlabel('b')
plt.ylabel('d')
plt.show()

这会产生:

此外,3D 绘图往往会阻碍查看所有数据(因为尖峰隐藏了其后面的东西)。我会推荐 pcolormesh 或轮廓图。在后一种情况下,最后 6 行变为:

plt.contourf(B, D, nu)
plt.colorbar()
plt.xlabel('b')
plt.ylabel('d')
plt.show()

产生:


3
投票

这应该有效: 我不是 Python 专家,尤其是两个 for 循环可能非常不Python,但它完成了工作。

import math
import matplotlib.pyplot as plt
import numpy as np

b = np.arange(0.2, 3.2, 0.2)
d = np.arange(0.1, 1.0, 0.1)
nu = np.zeros( (b.size, d.size) )
counter_y = 0

for deta in d:
    counter_x = 0
    for beta in b:
        nu[counter_x, counter_y] = math.sqrt( 1 + (2*deta*beta)**2 ) / math.sqrt( (1-beta**2)**2 + (2*deta*beta)**2)
        counter_x += 1
    counter_y += 1

X, Y = np.meshgrid(d, b)

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.plot_surface(X, Y, nu)

1
投票

您需要首先创建一个

matplotlib figure

fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

此外,所有变量的大小都应该相同。因此,您的变量

d
应该是与其他变量长度相同的数组。

如果将变量

d
转换为长度为
0.1
510
数组,你会得到以下结果。

import math
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D


nu = []
b = [0.1 + i / 100 for i in range(0, 510)]
d = 0.1


for beta in b:
    nu.append( math.sqrt(1+(2*d*beta)**2)/ math.sqrt((1-beta**2)**2+(2*d*beta)**2))

#turned d into array of length 510 with 0.1 for each value
d = np.ones(510)*0.1


fig = plt.figure()
ax = Axes3D(fig)
ax.plot(b, d, nu)
plt.show()

你得到:


0
投票

这是 MalteHerrmann 的答案,但没有

for
循环。

import math
import matplotlib.pyplot as plt
import numpy as np

b = np.arange(0.2, 3.2, 0.2)
d = np.arange(0.1, 1.6, 0.1) # changed a bit the interval
nu = np.zeros( (b.size, d.size) )

for i in range (len(d)):
    for j in range (len(b)):
        nu[i,j] = math.sqrt( 1 + (2*d[i]*b[j])**2 ) / math.sqrt( (1-b[j]**2)**2 + (2*d[i]*b[j])**2)

X, Y = np.meshgrid(d, b)

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
ax.plot_surface(X, Y, nu)
© www.soinside.com 2019 - 2024. All rights reserved.