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

Jac*_*ues 5 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]
Run Code Online (Sandbox Code Playgroud)

我想绘制 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)

来自 Lacroix 等人的图。

我在添加颜色条时遇到了麻烦,我尝试从颜色图中提取 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()
Run Code Online (Sandbox Code Playgroud)

目前的结果:

绘图结果

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

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

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

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

Joh*_*anC 2

这是一种可能的方法。由于“headValues”未排序,间距也不相等,甚至使用了两次,因此尚不完全清楚最期望的结果是什么。

一些备注:

  • 在 matplotlib 中创建颜色条的标准方法不需要单独的子图。Matplotlib 将稍微缩小现有绘图,并将颜色条放在它旁边(或垂直条放在下面)。
  • 将“headValues”转换为 numpy 数组可以实现紧凑的代码,例如rgba = cmap(headValues)直接写入计算完整的数组。
  • 对未更改的值调用 cmap 会将 0 映射到最低颜色,将 1 映射到最高颜色,因此对于仅介于 0.16 和 0.44 之间的值,它们都将映射到非常相似的颜色。一种方法是创建一个范数,将 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()
Run Code Online (Sandbox Code Playgroud)

或者,可以使用颜色图中的位置来分配颜色,但无需创建

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))
Run Code Online (Sandbox Code Playgroud)

要获取每个“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]])
Run Code Online (Sandbox Code Playgroud)

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

演示图