【问题标题】:Plotting spatial data on a heatmap在热图上绘制空间数据
【发布时间】:2020-12-18 14:46:57
【问题描述】:

我有一个尚未解决的具有挑战性的问题。所以,我有一堆来自流体流动模拟的数据。我有两个文件:空间 (x,y,z) 数据,看起来像这样(注意,我只关心 2D,所以只关心 x 和 y 值):

(-2 -1.5 0.1)
(5 -1.5 0.1)
(-2 -1.5 0.6)
(5 -1.5 0.6)
(-2 1.92708 0.1)
...

及其对应的velocity_magnitude 值。其中每一行对应于空间数据文件中该位置的 velocty_x。例如,值 0.08 为 (-2 -1.5 0.1)。

0.08 
0.07
0.1 
0.34 ...
...

我想把它做成热图。我天真地首先只关注速度数据,重新格式化为二维数组,并显示热图,但位置都是错误的。问题是空间数据不按顺序排列,所以按我的方式做是行不通的。如何将 x,y 位置与实际速度值结合起来为我的数据创建热图?

【问题讨论】:

  • 我猜你想评估热图每个像素的速度平均值
  • 你有多次相同的 (x,y) 坐标,你需要决定你想要哪一个。很可能您的空间数据间隔不合适,因此您需要重新采样/插值。为热图创建一个数组并将样本放在数组上并绘制热图
  • 我添加了渲染数据的替代方法和导入文件的商品,如果它解决了您的问题,请告诉我。干杯

标签: python numpy text heatmap spatial


【解决方案1】:

如果您对在热图 Matplotlib 上渲染平均速度感兴趣,Numpy 和 Scipy 是您感兴趣的软件包。让我们调查一下您的一些选择...

数据可视化

试验数据集

首先我们创建一个试验数据集:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
   
# Create trial dataset:
N = 10000
a = np.array([-10, -10, 0])
b = np.array([15, 15, 0])
x0 = 3*np.random.randn(N, 3) + a
x1 = 5*np.random.randn(N, 3) + b
x = np.vstack([x0, x1])
v0 = np.exp(-0.01*np.linalg.norm(x0-a, axis=1)**2)
v1 = np.exp(-0.01*np.linalg.norm(x1-b, axis=1)**2)
v = np.hstack([v0, v1])

# Render dataset:
axe = plt.axes(projection='3d')
axe.plot_trisurf(x[:,0], x[:,1], v, cmap='jet', alpha=0.5)
axe.set_xlabel("x")
axe.set_ylabel("y")
axe.set_zlabel("Speed")
axe.view_init(elev=25, azim=-45)

看起来像:

二维六边形直方图

最简单的方法大概是使用 Matplotlib hexbin 函数:

# Render hexagonal histogram:
pc = plt.hexbin(x[:,0], x[:,1], C=v, gridsize=20)
pc.axes.set_title("Heatmap")
pc.axes.set_xlabel("x")
pc.axes.set_ylabel("y")
pc.axes.set_aspect("equal")
cb = plt.colorbar(ax=pc.axes)
cb.set_label("Speed")

它呈现:

二维矩形直方图

你也可以使用numpy.histogram2D 和 Matplolib imshow

# Bin Counts:
c, *_ = np.histogram2d(x[:,0], x[:,1], bins=20)
# Bin Weight Sums:
s, xbin, ybin = np.histogram2d(x[:,0], x[:,1], bins=20, weights=v)
lims = [xbin.min(), xbin.max(), ybin.min(), ybin.max()]

# Render rectangular histogram:
iax = plt.imshow((s/c).T, extent=lims, origin='lower')
iax.axes.set_title("Heatmap")
iax.axes.set_xlabel("x")
iax.axes.set_ylabel("y")
iax.axes.set_aspect("equal")
cb = plt.colorbar(ax=iax.axes)
cb.set_label("Speed")

它输出:

线性插值

正如@rioV8 所指出的,您的数据集在空间上似乎是不规则的。如果需要将其映射到矩形网格,可以使用mutlidimensional linear interpolator of Scipy

from scipy import interpolate

# Create interpolator:
ndpol = interpolate.LinearNDInterpolator(x[:,:2], v)

# Create meshgrid:
xl = np.linspace(-20, 30, 20)
X, Y = np.meshgrid(xl, xl)
lims = [xl.min(), xl.max(), xl.min(), xl.max()]

# Interpolate over meshgrid:
V = ndpol(list(zip(X.ravel(),Y.ravel()))).reshape(X.shape)

# Render interpolated speeds:
iax = plt.imshow(V, extent=lims, origin='lower')
iax.axes.set_title("Heatmap")
iax.axes.set_xlabel("x")
iax.axes.set_ylabel("y")
iax.axes.set_aspect("equal")
cb = plt.colorbar(ax=iax.axes)
cb.set_label("Speed")

它呈现:

注意:在这个版本中,刻度仍然需要以每个像素为中心。

轮廓

一旦你有了一个矩形网格,你也可以绘制 Matplotlib contours:

# Render contours:
iax = plt.contour(X, Y, V)
iax.axes.set_title("Contours")
iax.axes.set_xlabel("x")
iax.axes.set_ylabel("y")
iax.axes.set_aspect("equal")
iax.axes.grid()
iax.axes.clabel(iax)

数据处理

根据您提供的文件格式,使用 pandas 很容易导入:

import io
import pandas as pd
    
with open("spatial.txt") as fh:
    file1 = io.StringIO(fh.read().replace("(", "").replace(")", ""))
x = pd.read_csv(file1, sep=" ", header=None).values

v = pd.read_csv("speed.txt", header=None).squeeze().values

【讨论】:

  • 非常感谢您!这很有帮助,而且很有效。
  • @smokbel_06 我很高兴它有效,如果您认为合适,可以将其标记为答案。干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多