【问题标题】:Plot 4D data heatmap in Python在 Python 中绘制 4D 数据热图
【发布时间】:2021-05-15 08:33:32
【问题描述】:

嘿,我怎样才能在 3D 中绘制 2D 热图?现在我创建了一个 python 脚本来使用来自 CSV 的数据(CSV 格式:x、y、z、v)制作一个 2D 热图。 例如:

第一个 csv

0,000;-110,000;110,000;0,101

第二个 csv

0,000;-66,000;110,000;0,104

第三个 csv

0,000;-22,000;110,000;0,119

....

在此示例中,它是 xz 平面中的热图,我创建了例如另外五个图,这样我就可以在 3D 房间中插入六个 xz 平面图。 在4D heatmap plot with matplotlib 中有一个很好的例子。但我不知道如何在我的情况下使用它。

import numpy as np
import os
import matplotlib.pyplot as plt
from scipy.interpolate import griddata


'Create a list for every parameter'
x = []
y = []
z = []
v = []

file_path = "path/."

'Insert data from csv into lists'
for root, dirs, files in os.walk(file_path, topdown=False):
   for name in files:
       if name[-4:] != '.csv': continue
       with open(os.path.join(root, name)) as data:
          data = np.genfromtxt((line.replace(',', '.') for line in data), delimiter=";")
          if data[1] == 22: 
            x.append(data[0])
            y.append(data[1])
            z.append(data[2])
            v.append(data[3])

'Create axis data'
xi = np.linspace(min(x), max(x), 1000)
zi = np.linspace(min(z), max(z), 1000)
vi = griddata((x, z), v, (xi[None,:], zi[:,None]), method='cubic')

'Create the contour plot'
CS = plt.contourf(xi, zi, vi, 20, cmap=plt.cm.rainbow)
plt.title("Heatmap xz-plane", y=1.05, 
          fontweight="bold")
plt.xlabel("length x in cm")
plt.xticks(np.arange(0, 201, step=40))
plt.ylabel("height z in cm")
plt.yticks(np.arange(110, 251, step=20))
cbar = plt.colorbar()
cbar.set_label("velocity v in m/s", labelpad=10)
plt.savefig('testplot.png', dpi=400)  
plt.show()

满足@keepAlive 的请求,希望看到他未经测试的答案的结果...:

实际上效果很好:-)

【问题讨论】:

  • 所有数据文件的结构是否相同?我认为向我们展示您的数据的外观可能有助于我们弄清楚您想要实现的目标。否则,很难说出你在做的时候到底在想什么,例如。 data[1] == 22.... 在这个问题上可能还有更好的方法。
  • 是的,所有 csv 文件的结构为:x;y;z;v。但每个参数只有一个数据(一行)。每个 csv 文件都有以下输入,例如50,0;80,0;120,0;1,536if data[1] == 22 的 if 语句就是一个例子,因为原始代码要长得多,但对函数不感兴趣
  • 好的。我已经更新了我的问题并插入了三个 csv 文件的数据。还是您需要更多?
  • 嘿@nico.wagner 我真的很好奇您的帐户为何被删除。可能有一天你会看到这条评论,然后回复我……

标签: python 3d 2d heatmap


【解决方案1】:

免责声明:我是cited example的作者,所以我认为复制/粘贴自己不是问题。

请注意,您的数据集看起来(至少)不是 3 维的。但我会假设存在不情愿的选择偏差。

您首先需要汇总每个高度级别的“点”,我认为这是您的向量的第三个组成部分。一旦聚集,它们将构成你的位面。

# libraries
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import scipy.interpolate as si
from matplotlib import cm
import collections as co  # <------------------
import pandas as pd
import numpy as np

planes = co.defaultdict(list)

for root, dirs, files in os.walk(file_path, topdown=False):
   # [...]
       # [...]
       # [...]
          # [...]
          # [...]
            level = data[2]  # <------ third component.
            planes[level].append(data)

现在,在那个阶段,我们有一个每个level 的数组列表。让我们定义我们的grids_maker 函数

def grids_maker(arrays_list, colnames=list('xyzg')):
    # 0- The idea behind `list('xyzg')` is only to change the order
    #    of names, not the names as such. In case for example you
    #    want to use another component than the third to organize
    #    your planes.
    # 1- Instantiate a dataframe so as to minimize the modification
    #    of the function copied/pasted pasted from
    #    https://stackoverflow.com/a/54075350/4194079
    # 2- Pandas is also going to do some other jobs for us, such as
    #    stacking arrays, etc....
    df = pd.DataFrame(arrays_list, columns=colnames)

    # Make things more legible
    xy = df.loc[:, ['x', 'y']]
    x  = xy.x
    y  = xy.y
    z  = df.z
    g  = df.g
    reso_x = reso_y = 50
    interp = 'cubic' # or 'nearest' or 'linear'

    # Convert the 4d-space's dimensions into grids
    grid_x, grid_y = np.mgrid[
        x.min():x.max():1j*reso_x,
        y.min():y.max():1j*reso_y
    ]

    grid_z = si.griddata(
        xy, z.values,
        (grid_x, grid_y),
        method=interp
    )

    grid_g = si.griddata(
        xy, g.values,
        (grid_x, grid_y),
        method=interp
    )

    return {
        'x' : grid_x,
        'y' : grid_y,
        'z' : grid_z,
        'g' : grid_g,
    }

让我们在我们的数组列表上使用grids_maker 并获取每个 z 级别的第 4 维的极值。

g_mins = []
g_maxs = []
lgrids = {}

for level, arrays_list in planes.items():
    lgrids[level] = grids = grids_maker(arrays_list)
    g_mins.append(grids['g'].min())
    g_maxs.append(grids['g'].max())

让我们创建我们的(所有文件统一的)色标并显示绘图。

# Create the 4th color-rendered dimension
scam = plt.cm.ScalarMappable(
    norm=cm.colors.Normalize(min(g_mins), max(g_maxs)),
    cmap='jet' # see https://matplotlib.org/examples/color/colormaps_reference.html
)
fig = plt.figure()
ax  = fig.gca(projection='3d')
for grids in lgrids.values(): 
    scam.set_array([])   
    ax.plot_surface(
        grids['x'], grids['y'], grids['z'],
        facecolors  = scam.to_rgba(grids['g']),
        antialiased = True,
        rstride=1, cstride=1, alpha=None
    )
plt.show()

我很高兴看到结果。

【讨论】:

  • 有任何问题@nico 吗?
  • 没有。它工作得很好。在我编辑的问题中看到这两张图片。谢谢!
  • 谢谢你的照片@nico(!)总是很高兴看到这个!
猜你喜欢
  • 2019-06-02
  • 1970-01-01
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
  • 2019-11-06
  • 2018-02-04
  • 2021-02-27
相关资源
最近更新 更多