【问题标题】:Connecting dots in a 2D scatterplot with a color as a third dimension连接二维散点图中的点,颜色作为第三维
【发布时间】:2019-11-28 10:36:26
【问题描述】:

假设我有以下数据集:

x = np.arange(150000,550000,100000)
y = np.random.rand(7*4)
z = [0.6,0.6,0.6,0.6,0.7,0.7,0.7,0.7,0.8,0.8,0.8,0.8,0.9,0.9,0.9,0.9,1.0,1.0,1.0,1.0,1.1,1.1,1.1,1.1,1.2,1.2,1.2,1.2]

x_ = np.hstack([x,x,x,x,x,x,x])

我正在做一个散点图:

plt.figure()
plt.scatter(x_,y,c=z)
plt.colorbar()
plt.set_cmap('jet')
plt.xlim(100000,500000)
plt.show()

但是,我想连接相同颜色的点。我尝试只使用具有相同变量的plt.plot,但它连接了所有点,而不仅仅是黄点和黄点。

感谢任何帮助。

编辑:

z 轴是离散的,我事先知道这些值。另外我知道我可以多次调用plt.plot() 方法来绘制线条,但我希望可能有另一种方法。

【问题讨论】:

    标签: python matplotlib scatter-plot


    【解决方案1】:

    使用LineCollection 更容易:

    import matplotlib.pyplot as plt
    from matplotlib.collections import LineCollection
    import numpy as np; np.random.seed(42)
    
    x = np.arange(150000,550000,100000)
    y = np.random.rand(7*4)
    z = [0.6,0.6,0.6,0.6,0.7,0.7,0.7,0.7,0.8,0.8,0.8,0.8,0.9,0.9,0.9,0.9,1.0,1.0,1.0,1.0,1.1,1.1,1.1,1.1,1.2,1.2,1.2,1.2]
    
    x_ = np.tile(x, 7)
    segs = np.stack((x_, y), axis=1).reshape(7, 4, 2)
    
    
    plt.figure()
    sc = plt.scatter(x_,y,c=z, cmap="plasma")
    plt.colorbar()
    
    lc = LineCollection(segs, cmap="plasma", array=np.unique(z))
    plt.gca().add_collection(lc)
    
    plt.show()
    

    【讨论】:

    • 这正是我想要的:)
    【解决方案2】:

    如果我理解正确,您有一个 x 值列表,并且每个 x 都有一些 y 相关联,每个 x,y 都有一个特定的 z 值。 z 值属于有限集(或可以四舍五入以确保只有有限集)。

    所以,我创建了 x、y 和 z 的副本,并通过 z 同时对它们进行排序。 然后,遍历 z 数组,收集 x,y,每次 z 变化时,都可以绘制属于该颜色的所有线。 为了不需要特殊的步骤来绘制最后一组线,我附加了一个标记。

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.arange(150000,550000,100000)
    y = np.random.rand(7*4)
    z = [0.6,0.6,0.6,0.6,0.7,0.7,0.7,0.7,0.8,0.8,0.8,0.8,0.9,0.9,0.9,0.9,1.0,1.0,1.0,1.0,1.1,1.1,1.1,1.1,1.2,1.2,1.2,1.2]
    z_min = min(z)
    z_max = max(z)
    
    x_ = np.hstack([x,x,x,x,x,x,x])
    
    zs = [round(c, 1) for c in z]  # make sure almost equal z-values are exactly equal
    zs, xs, ys = zip( *sorted( zip(z, x_, y) ) )  # sort the x,y via z
    zs += (1000,) # add a sentinel at the end that can be used to stop the line drawing
    xs += (None, )
    ys += (None, )
    
    plt.set_cmap('plasma')
    cmap = plt.get_cmap()  # get the color map of the current plot call with `plt.get_cmap('jet')`
    norm = plt.Normalize(z_min, z_max) # needed to map the z-values between 0 and 1
    
    plt.scatter(x_, y, c=z, zorder=10)  # z-order: plot the scatter dots on top of the lines
    prev_x, prev_y, prev_z = None, None, None
    x1s, y1s, x2s, y2s = [], [], [], []
    for x0, y0, z0 in zip(xs, ys, zs):
        if z0 == prev_z:
            x1s.append(prev_x)
            y1s.append(prev_y)
            x2s.append(x0)
            y2s.append(y0)
        elif prev_z is not None:  # the z changed, draw the lines belonging to the previous z
            print(x1s, y1s, x2s, y2s)
            plt.plot(x1s, y1s, x2s, y2s, color=cmap(norm(prev_z)))
            x1s, y1s, x2s, y2s = [], [], [], []
        prev_x, prev_y, prev_z = x0, y0, z0
    
    plt.colorbar()
    plt.show()
    

    这是你的意思吗?

    【讨论】:

    • 嗯,我想也只是对数据进行排序并单独绘制它们。我的意思是我不一定需要带有颜色条的散点图。但是,我认为可以让plt.scatter() 为我这样做,因为数据可能已经以某种方式排序以适合颜色条比例。我会再等一会儿,看看是否有人知道这是否可能,而无需自己对数据进行排序。如果没有,我会接受你的回答。无论如何感谢您的帮助:)
    • Scatter 不需要按颜色排序。事实上,所有颜色都可以不同。它只是在绘制每个点时计算颜色。颜色计算类似于color_index = int((z - z_min) / (z_max - z_min) * 256)
    • 好吧,我明白了。那么在那种情况下,我接受了你的回答。感谢这么多的努力。我有最后一个问题,知道如何将线条设置为与点相同的颜色吗?
    • 好的,所以我尝试了:cbar = plt.colorbar() cbar.set_cmap('jet') for i in range(int(len(zs)/4)): ax.plot(xs[i*4:(i+1)*4],ys[i*4:(i+1)*4], color=cbar.cmap(zs[i*4])),然后尝试通过cbar.cmap(zs[i*4]) 访问我知道数据分成 4 部分。但是我得到不同的颜色。我传递了错误的值吗?不用着急。如果您有时间详细说明,那就太好了。如果不是,我相信我最终会弄明白的。
    • 您需要标准化步骤。查看更新的代码。
    猜你喜欢
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 2021-12-26
    • 2014-02-18
    • 2012-01-02
    • 2013-02-13
    相关资源
    最近更新 更多