【问题标题】:Plotting data of unequal size or x-vector in an intensity plot在强度图中绘制大小不等的数据或 x 向量
【发布时间】:2022-01-06 16:04:53
【问题描述】:

假设你有以下数据:

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. 二维数组中的所有行/列都需要具有相同的长度。这是两个问题中的次要问题,因为我总能找出最长的数据集并用例如 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()can 那样将多个不同数据的数组绘制成强度图。理想情况下,我需要告诉它可以预期的强度图,在本例中,2 个水平数据切片,然后提供 x 数据(绘制在 x 轴上)、y 数据(绘制在colorbar) 用于该图应进入的切片的每个索引。您知道实现此目的的方法或任何能够实现此目的的软件包吗?

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

【问题讨论】:

  • 您的数据集在第一部分是一维的,在第二部分是二维的。 x 和 y 坐标告诉 matplotlib 在 2D 监视器上绘制点的位置(实际上是线段)。在第二种情况下,您希望您的输出是什么样的?
  • 所以基本上,有什么能力,究竟是什么?
  • 1) pcolormesh 还绘制二维数组,它们具有 xscale 和 yscale。您还可以使用extents kwarg 在 imshow 中伪造 x/y 比例。 2) pcolormesh 和 imshow 都不要求列数等于行数。

标签: python numpy matplotlib plot


【解决方案1】:

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

这里对答案稍作修改(只是为了传递绘图变量):Color line by third variable - Python

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)

【讨论】:

    【解决方案2】:

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

    这接受坐标和值。在这种情况下,您有一个 2D 网格,因此您需要一个用于 x 坐标的 2D 数组、一个用于 y 坐标的 2D 数组和一个用于值的 2D 数组。

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

    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)
    
    

    【讨论】:

    • 基本上,这几乎是我需要的,除了我要绘制的数组不是 2D,而是 1D。基本上我需要的是X1, Y1 = np.meshgrid(np.arange(0, 10, 1), [0])。由于某种原因,这不会绘制,而X1, Y1 = np.meshgrid(np.arange(0, 10, 1), [0,1]) 会。它们都是二维数组,尽管第一个具有形状 (10,1) 而第二个具有形状 (10,2)。但是,是的,如果我可以绘制一个仅包含 1 行的二维数组,这就是我需要的......
    • 我认为 pcolormesh 需要一个单元格的所有 4 个角来绘制它 - 文档中的 X,Y 参数中有一个有用的图表。
    • 我可能误解了你的问题——如果每一行都有数组x, y, c,并且你希望x[i], y[i]线上的点有颜色c[i],那么这样的事情应该会有所帮助:@987654323 @
    • 不,我认为您第一次理解正确。您的代码和我的真实代码之间的区别在于您创建了二维数组并仅绘制了它们。我只有一维数组....想象一下,如果您的“明亮”数据只是一个水平切片,例如 y 轴(垂直比例)值为 0。而“黑暗”数据位于 y 轴比例共 5 个。您将得到 2 个 1D 切片,而不是图中的两个 2D 数组。这就是我需要的。
    • ... 这样我就会得到这样的情节:imgur.com/a/GHQHv8p
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      处理 wtw 的第一个答案我想出了一个方法,这有点 hacky... 使用他们的方法,我无法绘制我的 1D 数组,因此我通过将 2 个相同的数组堆叠在一起使它们成为 2D。然后我指定这些应该绘制在什么 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")
      

      生成下图:

      【讨论】:

        猜你喜欢
        • 2016-10-12
        • 2017-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-05
        • 2016-02-29
        相关资源
        最近更新 更多