需要帮助制作 3D 曲面图和 4D 曲面图,并以颜色作为单独的维度

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

正如标题所说。我尝试了很多不同的方法来做到这一点。我有 4 个长度为 48 的向量。

X: [ 25  25  25  25  25  25  50  50  50  50  50  50  75  75  75  75  75  75
 100 100 100 100 100 100 125 125 125 125 125 125 150 150 150 150 150 150
 175 175 175 175 175 175 200 200 200 200 200 200]
Y: [ 100  250  500 1000 1500 2000  100  250  500 1000 1500 2000  100  250
  500 1000 1500 2000  100  250  500 1000 1500 2000  100  250  500 1000
 1500 2000  100  250  500 1000 1500 2000  100  250  500 1000 1500 2000
  100  250  500 1000 1500 2000]
Z: [ 0.20900428  0.51286209  1.03853414  3.28220448  4.6407558   7.34891026
  0.2765902   0.7604821   1.76022537  5.10049512  8.61249235 12.96447849
  0.2623122   0.98286221  2.5040107   6.2533442  11.0721308  15.36910634
  0.32121766  0.97078288  2.66376145  7.51123161 12.98652091 20.21016505
  0.38653798  1.21371622  3.30200138  7.93705671 17.20774968 28.97923372
  0.46758823  1.23861806  3.72943289  8.38099084 19.04535632 32.7009341
  0.44258697  1.42894619  3.96008332 10.45831311 22.98130064 31.32277734
  0.4507597   1.7036628   4.69553339 10.92697349 25.68610439 45.02457106]
C: [38.96 39.48 40.34 41.04 41.08 41.06 39.76 40.62 40.88 41.06 41.04 41.2
 39.22 40.48 40.98 41.2  41.26 41.16 40.2  40.78 40.68 41.26 41.26 41.32
 39.96 40.56 40.86 41.26 41.26 41.52 40.36 40.6  41.22 41.26 41.78 41.7
 39.24 40.8  41.26 41.4  41.92 41.62 39.74 41.06 41.24 41.56 41.94 42.06]

这段代码

X = overall_results.num_generations.values
Y = overall_results.population_size.values
Z = overall_results.avg_time.values
C = overall_results.avg_reward.values 
# note, C is not used as this is meant to be a fully working example
fig = plt.figure(figsize=(8,6))
ax = Axes3D(fig, auto_add_to_figure=False)
fig.add_axes(ax)
surf = ax.plot_trisurf(X, Y, Z, cmap=cm.jet, linewidth=.2)
ax.view_init(elev=5, azim=-140)
colorbar = fig.colorbar(surf, ax=ax, pad=0.1, shrink=.5, ticks=[5, 10, 15, 20, 25, 30], format="%d")
colorbar.ax.set_yticklabels(['<= 5', '10', '15', '20', '25', '>= 30'])
plt.title('GA Time Analysis by Population Size and Number of Generations')

plt.show()

产生这个数字

颜色映射到Z,我尝试合并C的各种方法都抛出错误。这也使用trisurf,并且,polycount非常低。

这段代码

X = overall_results.num_generations.values
Y = overall_results.population_size.values
Z = overall_results.avg_time.values
C = overall_results.avg_reward.values

# Define a finer grid for interpolation
new_X = np.linspace(X.min(), X.max(), 100)
new_Y = np.linspace(Y.min(), Y.max(), 100)
new_X, new_Y = np.meshgrid(new_X, new_Y)

# Perform interpolation
new_Z = griddata((X, Y), Z, (new_X, new_Y), method='linear')

# Create the 3D plot
fig = plt.figure(figsize=(8, 8))
ax = Axes3D(fig, auto_add_to_figure=False)
fig.add_axes(ax)

surf = ax.plot_surface(new_X, new_Y, new_Z, cmap=cm.jet, antialiased=True)

ticks = np.linspace(Z.min(), Z.max(), 10)
#ticks = [5, 10, 15, 20, 25, 30, 35, 40, 45]

colorbar = fig.colorbar(surf, ax=ax, pad=0.1, shrink=0.35, ticks=ticks, format="%d")
#colorbar.ax.set_yticklabels(['<= 5', '10', '15', '20', '25', '>= 30'])

ax.view_init(elev=8, azim=-150)
plt.title('GA Time Analysis by Population Size and Number of Generations')
ax.set_xlabel('Number of Generations', labelpad=12, fontsize=14)
ax.set_ylabel('Population Size', labelpad=12, fontsize=14)
ax.zaxis.set_rotate_label(False)
ax.set_zlabel('Running Time (seconds)', rotation=90, fontsize=14)
plt.show()

产生这个数字

一个更好看的图形,并使用plot_surface而不是trisurf。但同样,我无法使用 C 来设置颜色条。我看过

绘制 3D 表面,其中颜色图作为第四维,x、y、z 的函数

如何使用任意数据使用 matplotlib 制作 4D 绘图

带有表面梯度的 Color matplotlibplot_surface 命令

使用的库

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from scipy.interpolate import griddata
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from matplotlib.ticker import MaxNLocator
from matplotlib.colors import Normalize

现在,我可以创建一个散点图来完成我想要的操作,减去表面,就像这样

X = overall_results.num_generations.values
Y = overall_results.population_size.values
Z = overall_results.avg_time.values
C = overall_results.avg_reward.values

cmap = plt.get_cmap('jet')  # You can choose any colormap you prefer
norm = Normalize(vmin=C.min(), vmax=C.max())

fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='3d')
img = ax.scatter(X, Y, Z, c=C, s=100, cmap=cmap, norm=norm, alpha=1.0)
#plt.scatter(x, y, c=x, cmap=cmap, s=350, alpha=.7)
plt.xlabel('Average Reward', fontsize=14)
plt.ylabel('Running Time', fontsize=14)

cbar = fig.colorbar(img, pad=.1, shrink=.5)
cbar.set_label('Average Reward', fontsize=14, labelpad=10)
ax.view_init(elev=20, azim=-140)
plt.show()

产生这个数字

但我想要这种效果作为表面。

python matplotlib surface matplotlib-3d 4d
1个回答
0
投票

感谢 Gordon Stein 和 Caleb Vatral(去范德比尔特!),这是缺失的部分:

# Also color
new_C = griddata((X, Y), C, (new_X, new_Y), method='linear')

# Done to rescale it to show in color map, you likely need to change it
new_C = new_C - new_C.min()
new_C = cm.gist_rainbow(new_C / new_C.max())
surf = ax.plot_surface(new_X, new_Y, new_Z, facecolors=new_C, antialiased=True)

或者,

norm = (C - C.min()) / (C.max()-C.min())
new_C = griddata((X,Y), norm, (new_X, new_Y), method="linear")

colors = np.empty(new_X.shape, dtype=tuple)
for y in range(100):
    for x in range(100):
        colors[y, x] = cm.jet(new_C[x, y], )
surf = ax.plot_surface(new_X, new_Y, new_Z, facecolors=colors, antialiased=True)

通过一些颜色条操作,我们现在有了

© www.soinside.com 2019 - 2024. All rights reserved.