在强度图中绘制不等大小或 x 向量的数据

Plotting data of unequal size or x-vector in an intensity plot

假设您有以下数据:

x1_Length = 100
x1 = np.linspace(10,100,num=x1_Length)
y1 = np.linspace(0, 1.3, num=x1_Length)

x2_Length = 200
x2 = np.linspace(50, 200, num=x2_Length)
y2 = np.exp(np.linspace(0, 1, num=x2_Length))

如果你想绘制这个,那就很简单了:

fig, ax = plt.subplots()
ax.plot(x1,y1, ".g")
ax.plot(x2,y2, "--r")

这给出了预期的结果,即使绘制的阵列具有不同的长度并且不共享 x 数据。

现在,假设您想在强度图中绘制相同的数据。这会导致一些问题:

  1. 据我了解,强度图(例如 imshow)绘制二维阵列,因此没有 x 轴刻度或 y 轴刻度的直接概念。数据根据其在数组中的索引显示。在这里,这将是一个问题,因为两个数组的第一个元素不对应于相同的 x 值。

  2. 所有 rows/columns 需要在二维数组中具有相同的长度。这是两个问题中的次要问题,因为我总能找出最长的数据集并用例如 NaN 填充所有较短的数据集,如下所示:

dataset = [x1_data, x2_data]
max_Length = np.max([array[0,:].shape[0] for array in dataset ])
data_array = np.nan * np.ones((2*len(dataset), max_Length))
for i, spectrum_array2D in enumerate(dataset):
    length = spectrum_array2D[0,:].shape[0]
    firstRowOfInsertion = 2*i
    data_array[[firstRowOfInsertion, firstRowOfInsertion+1], :length] = spectrum_array2D

我没有看到任何技术限制,为什么不能像 plt.plot() 那样将多个不同数据阵列绘制成强度图。理想情况下,我需要的是告诉它可以预期的强度图,在这个例子中,2 个水平数据切片,然后提供 x 数据(绘制在 x 轴上),y 数据(绘制在colorbar) 对于该图应该进入的切片的每个索引。您知道实现此目的的方法或任何能够做到这一点的软件包吗?

编辑:最终,我想要一个看起来像这样的图,它是从下面的@wtw 建议中采纳的(这个图中的数据是随机的,我需要它是我的 y1 和 y2 数组):

据我了解,您知道,这两个数据集不能相互交叉。这是第一个重要条件。如果 to 值将占据 meshgrid 中的相同像素,将选择哪一个? 但即使数据不相交,当两个轴具有不同的采样 rates/distances 时,也可能会出现问题。在您可以将它们都绘制在同一图像甚至网格中之前,您必须 resample/interpolate 两个阵列都位于相同的网格上。这很快就变得非常棘手并且容易出错。 如果我要尝试这个,我会首先创建单独的颜色贴图,使用相同的颜色代码,但两个独立的网格。下一步是将一个图形放在另一个图形之上并移动它以使轴对齐;基本上是一个插图。我想在 matplotlib 中有一些最佳实践。

matplotlib 的一个选项是 pcolormeshhttps://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.pcolormesh.html

它接受坐标和值。在这种情况下,您有一个二维网格,因此您需要一个二维数组作为 x 坐标,一个二维数组作为 y 坐标,一个二维数组作为值。

您可以绘制不同的数据集,但如果它们的坐标重叠,您将不得不考虑如何显示这些数据集。一种选择是使第二个数据集稍微透明,以便您可以透过它看到第一个数据集。

import numpy as np
import matplotlib.pyplot as plt

# Create the first set of coordinates
X1, Y1 = np.meshgrid(np.arange(0, 10, 1), np.arange(0, 5, 0.5))
C1 = np.random.uniform(size=np.shape(X1))

# Second set of coordinates with smaller cells, slightly overlapping the first
X2, Y2 = np.meshgrid(np.arange(8, 12, 0.1), np.arange(4, 6, 0.1))
C2 = np.random.uniform(size=np.shape(X2))

# Plotting:
fig, ax = plt.subplots(1)

ax.pcolormesh(X1, Y1, C1)
ax.pcolormesh(X2, Y2, C2, alpha=0.25)

工作 wtw 的第一个答案我想出了一个方法,有点 hacky... 使用他们的方法我无法绘制我的一维数组,所以我通过将 2 个相同的数组堆叠在一起使它们成为二维的。然后,我指定应绘制的 y 轴值。这是我的最终代码:

import numpy as np
import matplotlib.pyplot as plt

x1_Length = 100
x1 = np.linspace(10,100,num=x1_Length)
z1 = np.linspace(0, 1.3, num=x1_Length)
x1_data = np.stack([x1,z1])

x2_Length = 200
x2 = np.linspace(50, 200, num=x2_Length)
z2 = np.exp(np.linspace(0, 4, num=x2_Length))
x2_data = np.stack([x2,z2])

x3_Length = 30
x3 = np.linspace(50, 150, num=x3_Length)
z3 = np.sin(np.linspace(0, 4, num=x3_Length))
x3_data = np.stack([x3,z3])

y_data = [-1, 5, 12]
stepsize = np.min(np.abs(np.diff(y_data)))
dataset = [x1_data, x2_data, x3_data]

fig, ax = plt.subplots(1)

for i, spectrum_array2D in enumerate(dataset):
    X, Y = np.meshgrid(spectrum_array2D[0,:], [y_data[i]-stepsize/4, y_data[i]+stepsize/4]); print(f"X has shape {X.shape}, Y has shape {Y.shape}")
    Z = np.vstack( [spectrum_array2D[1,:], spectrum_array2D[1,:]] ); print(f"Z has shape {Z.shape}")
    ax.pcolormesh(X, Y, Z)

ax.set_yticks(y_data)
ax.set_xlabel("x")
ax.set_ylabel("y")

产生下图:

经过讨论,我认为需要的是一条用 x 点和颜色值绘制的线,每次可能具有不同的 y 值。

对这里的答案稍作修改(只是为了传递绘图变量):

import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np

def plot_colourline(x,y,c, **xargs):
    c = cm.viridis((c-np.min(c))/(np.max(c)-np.min(c)))
    ax = plt.gca()
    for i in np.arange(len(x)-1):
        ax.plot([x[i],x[i+1]], [y[i],y[i+1]], c=c[i], **xargs)
    return

# First data set
x1 = np.arange(0, 10, 1)
y1 = np.zeros(len(x1))  # use 0 as the y value for all points
c1 = np.random.uniform(size=len(x1))

# Second dataset, different number of points, x values and y value
x2 = np.arange(8, 12, 0.1)
y2 = np.ones(len(x2))  # Use 1 as the y value for all points
c2 = np.random.uniform(size=len(x2))

fig, ax = plt.subplots(1)
plot_colourline(x1, y1, c1, linewidth=5)
plot_colourline(x2, y2, c2, linewidth=5, alpha=0.5)