matplotlib 需要帮助将3D表面图转换为4D表面图,颜色作为单独的维度

mepcadol  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(108)

正如标题所说。我已经尝试了很多不同的方法来做到这一点。我有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()

得出这个数字

颜色被Map到Z,我尝试过的各种方法都是抛出错误的。这也使用了trisurf,而且,多边形计数非常低。
此代码段

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来设置颜色条。我看过
Plot 3d surface with colormap as 4th dimension, function of x,y,z
How to make a 4d plot with matplotlib using arbitrary data
带有表面渐变的颜色matplotlib plot_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()

从而得出这个数字

但我喜欢这种效果作为一个表面。

yhuiod9q

yhuiod9q1#

感谢戈登·斯坦和凯莱布·瓦特尔(加油范德比尔特!),这是缺失的一部分:

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

通过一些颜色条的处理,

相关问题