【问题标题】:Python surface plottingPython 曲面绘图
【发布时间】:2020-05-12 14:59:05
【问题描述】:

我有下表数据(请看图片) 我想在 python 中有一个曲面图。使用 ma​​tplotlib 中的曲面绘图,

import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X=[2,3,5,8,20,30,50,80,100,150,175,200,250,300]
Y=[2,3,4,5,10,15,20,30,40,50,80,100,125,150,175,200]
Y,X=np.meshgrid(Y,X)
Z=np.array([
[0.2885307,0.269452,0.259193,0.2548041,0.2731868,0.4801551,0.7992361,1.7577641,3.2611327,5.428839,19.647976,37.59729,78.0871,152.21466,268.14572,0],
[0.2677955,0.2538363,0.2380033,0.2306999,0.4779794,0.9251045,1.5448972,3.508644,6.4968576,11.252151,0,0,0,0,0,0],
[0.2432982,0.2283371,0.2514196,0.3392502,0,0,0,0,0,0,0,0,0,0,0,0],
[0.2342575,0.3158406,0.4770729, 0.6795485,2.353042, 5.260077,9.78172,25.87004,59.52568, 0,0,0,0,0,0,0],
[0.6735384, 1.3873291,2.346506, 3.5654,0,0,0,0,0,0,0,0,0,0,0,0],
[1.3584715, 2.9405127,5.096819,8.155857,0,0,0,0,0,0,0,0,0,0,0,0],
[3.558062,8.216592,15.768077,27.386694,0,0,0,0,0,0,0,0,0,0,0,0],
[9.537899,25.202589,58.20041,0,0,0,0,0,0,0,0,0,0,0,0,0],
[16.083374,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[54.936775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[89.185974,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]])

my_col = cm.jet(Z/np.amax(Z))
surf = ax.plot_surface(X, Y, Z,cmap=cm.coolwarm,linewidth=0, antialiased=False)
ax.set_zlim(0, 300)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

我得到这样的情节

这是正确的,但不是很有吸引力或直观。如何使可视化更加流畅和清晰?请注意,我的数据中有很多空白。我应该对空格使用“zero”还是“nan”(不是数字)?对于相同的数据,excel 显示的图表要好得多。 感谢您的投入,以使 python 绘图更具视觉吸引力。

【问题讨论】:

  • 生成前一个情节的代码在哪里?
  • 嗨,很抱歉。我现在已经添加了。
  • 没关系...我认为错误在于数据。你的情节和期待的情节看起来很相似。你确定所有这些零都存在于数据中吗
  • 我没有完全理解你的评论。所有这些零都在那里。我的意思是,这些数据在表格中
  • 我知道我的桌子有很多空白。我正在尝试从这些数据中绘制一个像样的图表。例如,我可以删除最后 3 行。但是在绘图、着色风格等方面有没有好的选择?

标签: python excel matplotlib mplot3d


【解决方案1】:

matplotlib 和 excel 图之间的区别在于 matplotlib 是在线性比例上绘制的,而 excel 是对数的(或者看起来像对数轴但实际上不是的东西——见下文)。因此,在 matplotlib 中,斜坡看起来非常陡峭,但在 excel 中,斜坡被原木显着拉长。

不幸的是,matplotlib 还没有在 3D 中正常工作的日志轴。我不知道为什么会这样,但这是一个严重的缺点。但是,如果您在绘图之前获取 X 和 Y 数据的log10,您可以看到类似于 Excel 的绘图。您还可以进一步 DIY 自己的日志轴,但我刚刚使用刻度格式化程序做了一个速记。

import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter, FuncFormatter
from mpl_toolkits.mplot3d import axes3d
import numpy as np

def format_log(x, pos=None):
    x1 = 10**x
    s = "%.3f" % x1
    return s[:-4] if s[-3:]=="000" else " "

fig = plt.figure()
ax = fig.gca(projection='3d')
X=[2,3,5,8,20,30,50,80,100,150,175,200,250,300]
Y=[2,3,4,5,10,15,20,30,40,50,80,100,125,150,175,200]
X = np.log10(np.array(X))
Y = np.log10(np.array(Y))
Y,X=np.meshgrid(Y,X)
Z=np.array([
[0.2885307,0.269452,0.259193,0.2548041,0.2731868,0.4801551,0.7992361,1.7577641,3.2611327,5.428839,19.647976,37.59729,78.0871,152.21466,268.14572,0],
[0.2677955,0.2538363,0.2380033,0.2306999,0.4779794,0.9251045,1.5448972,3.508644,6.4968576,11.252151,0,0,0,0,0,0],
[0.2432982,0.2283371,0.2514196,0.3392502,0,0,0,0,0,0,0,0,0,0,0,0],
[0.2342575,0.3158406,0.4770729, 0.6795485,2.353042, 5.260077,9.78172,25.87004,59.52568, 0,0,0,0,0,0,0],
[0.6735384, 1.3873291,2.346506, 3.5654,0,0,0,0,0,0,0,0,0,0,0,0],
[1.3584715, 2.9405127,5.096819,8.155857,0,0,0,0,0,0,0,0,0,0,0,0],
[3.558062,8.216592,15.768077,27.386694,0,0,0,0,0,0,0,0,0,0,0,0],
[9.537899,25.202589,58.20041,0,0,0,0,0,0,0,0,0,0,0,0,0],
[16.083374,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[54.936775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[89.185974,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]])
my_col = cm.jet(Z/np.amax(Z))
surf = ax.plot_surface(X, Y, Z,cmap=cm.coolwarm)
ax.set_zlim(0, 300)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax.xaxis.set_major_formatter(FuncFormatter(format_log))
ax.yaxis.set_major_formatter(FuncFormatter(format_log))
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

编辑:
回到这个问题后,我意识到 Excel 绘图实际上并没有显示对数轴,而是仅绘制给定的 XY 值,沿轴具有相等的间距即使是这些值也没有明确的数学级数。

请务必注意,这不是数据的良好表示,因为它给人的明显印象是它是对数的(对于所提供的特定数据),但实际上并非如此,尽管它需要非常仔细地检查才能看到.这里相邻数字之间的差距甚至不是单调的。

所以我不鼓励这种表示,但要重现该 Excel 图,我建议制作等间距的数据,但用不同的数字标记它(仅这句话就足以阻止这种方法)。但这里是代码和方法:

fig = plt.figure()
ax = fig.gca(projection='3d')
x=[2,3,5,8,20,30,50,80,100,150,175,200,250,300]
y=[2,3,4,5,10,15,20,30,40,50,80,100,125,150,175,200]

Y,X=np.meshgrid(range(len(y)),range(len(x)))
Z=np.array([
[0.2885307,0.269452,0.259193,0.2548041,0.2731868,0.4801551,0.7992361,1.7577641,3.2611327,5.428839,19.647976,37.59729,78.0871,152.21466,268.14572,0],
[0.2677955,0.2538363,0.2380033,0.2306999,0.4779794,0.9251045,1.5448972,3.508644,6.4968576,11.252151,0,0,0,0,0,0],
[0.2432982,0.2283371,0.2514196,0.3392502,0,0,0,0,0,0,0,0,0,0,0,0],
[0.2342575,0.3158406,0.4770729, 0.6795485,2.353042, 5.260077,9.78172,25.87004,59.52568, 0,0,0,0,0,0,0],
[0.6735384, 1.3873291,2.346506, 3.5654,0,0,0,0,0,0,0,0,0,0,0,0],
[1.3584715, 2.9405127,5.096819,8.155857,0,0,0,0,0,0,0,0,0,0,0,0],
[3.558062,8.216592,15.768077,27.386694,0,0,0,0,0,0,0,0,0,0,0,0],
[9.537899,25.202589,58.20041,0,0,0,0,0,0,0,0,0,0,0,0,0],
[16.083374,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[54.936775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[89.185974,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]])
my_col = cm.jet(Z/np.amax(Z))
surf = ax.plot_surface(X, Y, Z,cmap=cm.coolwarm)
ax.tick_params(axis='both', which='major', labelsize=6)
ax.set_zlim(0, 300)
ax.xaxis.set_major_locator(IndexLocator(1, 0))
ax.xaxis.set_major_formatter(FixedFormatter([repr(v) for v in x]))
ax.yaxis.set_major_locator(IndexLocator(1, 0))
ax.yaxis.set_major_formatter(FixedFormatter([repr(v) for v in y]))
fig.colorbar(surf, shrink=0.5, aspect=5)

如果想要显示为XY 给出的具体数字,一种解决方案是用对数轴绘制(因为数字以对数方式非常近似地间隔),然后绘制数字特别是通过轴上的线,或者,不要使用这些数字而不是通常的规则间隔的数字。 (但要将它们绘制为轴值,在视觉上以固定的间隔将它们隔开,这是一个问题。)

【讨论】:

  • 感谢您的回答,我有一个小疑问。是否可以沿 X 和 Y 轴显示所有值,而不仅仅是 10 和 100?
  • @SandeepParameshwara:是的,这是可能的,但很难找到一个通用的解决方案。需要发生的是让 matplotlib 以 3D 形式对数轴。 (在那之前,如果你需要一个特定情节的答案,根据我已经发布的内容尝试一些东西可能是合理的,如果你有问题,回来提出一个新的具体问题,例如,你需要:适用于所有范围、出版质量位置、刻度的良好积分值等。也许有人会这样做,但问题太大了,不能仅仅添加到这个问题和答案中。)
  • @SandeepParameshwara:我再次查看了这个,我在阅读您最初发布的情节时出错了。我认为这个错误确切地说明了为什么这些图不应该以它们在你的问题中的方式呈现,并且真正的log10 是正确的方法,但我仍然想纠正这个错误,所以我已经发布了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多