python - 添加一个颜色条,其颜色对应于现有图中的不同线条

标签 python matplotlib

我的数据集采用以下形式:

Data[0] = [headValue,x0,x1,..xN]
Data[1] = [headValue_ya,ya0,ya1,..yaN] 
Data[2] = [headValue_yb,yb0,yb1,..ybN]
...
Data[n] = [headvalue_yz,yz0,yz1,..yzN]

我想绘制 f(y*) = x,所以我可以用不同的颜色可视化同一图中的所有线图,每种颜色由 headervalue_y* 决定。

我还想添加一个颜色条,其颜色与线条匹配,因此与标题值匹配,因此我们可以直观地链接哪个标题值导致哪种行为。

这是我的目标:(来自 Lacroix B、Letort G、Pitayu L 等人的情节。微管动力学尺度与细胞大小设置主轴长度和装配时间。开发细胞。2018;45(4):496-511 .e6. doi:10.1016/j.devcel.2018.04.022)

plot from Lacroix et al.

我在添加颜色条时遇到了麻烦,我试图从颜色图中提取 N 种颜色(N 是我的不同 headValues 的数量,或列 -1),然后为每条线图添加对应的颜色,这里是我要澄清的代码:
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

Data = [['Time',0,0.33,..200],[0.269,4,4.005,...11],[0.362,4,3.999,...16.21],...[0.347,4,3.84,...15.8]]
headValues = [0.269,0.362,0.335,0.323,0.161,0.338,0.341,0.428,0.245,0.305,0.305,0.314,0.299,0.395,0.32,0.437,0.203,0.41,0.392,0.347]
# the differents headValues_y* of each column here in a list but also in Data
# with headValue[0] = Data[1][0], headValue[1] = Data[2][0] ...
cmap = mpl.cm.get_cmap('rainbow') # I choose my colormap
rgba = [] # the color container
for value in headValues:
    rgba.append(cmap(value)) # so rgba will contain a different color for each headValue

fig, (ax,ax1) = plt.subplots(2,1) # creating my figure and two axes to put the Lines and the colorbar
c = 0 # index for my colors
for i in range(1, len(Data)):
    ax.plot( Data[0][1:], Data[i][1:] , color = rgba[c])
    # Data[0][1:] is x, Data[i][1:] is y, and the color associated with Data[i][0]
    c +=  1


fig.colorbar(mpl.cm.ScalarMappable(cmap= mpl.colors.ListedColormap(rgba)), cax=ax1, orientation='horizontal')   
# here I create my scalarMappable for my lineplot and with the previously selected colors 'rgba' 
plt.show()

目前的结果:

Plot Result

如何在第一个轴的侧面或底部添加颜色条?

如何正确地为这个颜色条添加一个对应于不同 headValues 的比例?

如何使用链接 One color = One headValue 使颜色条比例和颜色与绘图上的不同线条匹配?

我曾尝试使用 scalarMappable 更方便的散点图,但没有任何解决方案允许我一次完成所有这些事情。

最佳答案

这是一种可能的方法。由于 'headValues' 没有排序,也没有等距,一个甚至被使用了两次,所以不完全清楚最想要的结果是什么。

一些备注:

  • 在 matplotlib 中创建颜色条的标准方法不需要单独的子图。 Matplotlib 将稍微减少现有绘图并将颜色条放在它旁边(或垂直条的下方)。
  • 将 'headValues' 转换为 numpy 数组允许紧凑的代码,例如写作 rgba = cmap(headValues)直接计算完整的数组。
  • 对未更改的值调用 cmap 会将 0 映射到最低颜色,将 1 映射到最高颜色,因此对于仅在 0.16 和 0.44 之间的值,它们都将映射到非常相似的颜色。一种方法是创建一个 norm将 0.16 映射到最低颜色,将 0.44 映射到最高颜色。在代码中:norm = plt.Normalize(headValues.min(), headValues.max())然后计算 rgba = cmap(norm(headValues)) .

  • import matplotlib as mpl
    import matplotlib.pyplot as plt
    import numpy as np
    
    headValues = np.array([0.269, 0.362, 0.335, 0.323, 0.161, 0.338, 0.341, 0.428, 0.245, 0.305, 0.305, 0.314, 0.299, 0.395, 0.32, 0.437, 0.203, 0.41, 0.392, 0.347])
    x = np.linspace(0, 200, 500)
    # create Data similar to the data in the question
    Data = [['Time'] + list(x)] + [[val] + list(np.sqrt(4 * x) * val + 4) for val in headValues]
    headValues = np.array([d[0] for d in Data[1:]])
    
    order = np.argsort(headValues)
    inverse_order = np.argsort(order)
    
    cmap = mpl.cm.get_cmap('rainbow')
    rgba = cmap(np.linspace(0, 1, len(headValues)))  # evenly spaced colors
    
    fig, ax = plt.subplots(1, 1)
    for i in range(1, len(Data)):
        ax.plot(Data[0][1:], Data[i][1:], color=rgba[inverse_order[i-1]])
        # Data[0][1:] is x, Data[i][1:] is y, and the color associated with Data[i-1][0]
    
    cbar = fig.colorbar(mpl.cm.ScalarMappable(cmap=mpl.colors.ListedColormap(rgba)), orientation='vertical',
                        ticks=np.linspace(0, 1, len(rgba) * 2 + 1)[1::2])
    cbar.set_ticklabels(headValues[order])
    plt.show()
    

    或者,可以使用它们在颜色图中的位置来分配颜色,但不创建

    cmap = mpl.cm.get_cmap('rainbow')
    norm = plt.Normalize(headValues.min(), headValues.max())
    
    fig, ax = plt.subplots(1, 1)
    for i in range(1, len(Data)):
        ax.plot(Data[0][1:], Data[i][1:], color=cmap(norm(Data[i][0])))
    cbar = fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm))
    

    要获取每个“headValues”的刻度,可以明确设置这些刻度。由于为每个刻度放置标签会导致文本重叠,因此可以将与其他标签太接近的标签替换为空字符串:

    headValues.sort()
    cbar2 = fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm), ticks=headValues)
    cbar2.set_ticklabels([val if val < next - 0.007 else '' for val, next in zip(headValues[:-1], headValues[1:])] 
                         + [headValues[-1]])
    

    左侧是第一种方法的结果(段中的颜色),右侧是替代颜色条(颜色取决于值):

    demo plots

    关于python - 添加一个颜色条,其颜色对应于现有图中的不同线条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61249245/

    相关文章:

    python - 如何优雅地将 zip 文件夹内容与解压缩文件夹内容进行比较

    python - matplotlib 在 mac osx 上挂起并且不显示图形

    python-3.x - 如何在 Seaborn 箱线图中调整 mustache 的大小?

    python - 如何根据列变量更改标记的形状?

    python - 当数据在元组中时如何在 matplotlib 中绘制直方图?

    python - win32 : get current DEVMODE of a monitor

    python - 如何使用 python apt 模块删除 ppa?

    Python - 如何完全清除列表中的整数?

    python - 有没有办法用 PIL 读取截断的 gif?

    python - 如何在标签中绘制带有汉字的图形