Добавление цветовой шкалы, цвет которой соответствует различным линиям в существующем графике - PullRequest
4 голосов
/ 16 апреля 2020

Мой набор данных имеет вид:

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

Как добавить цветовую шкалу сбоку или внизу первой оси?

Как правильно добавить шкалу для этой цветовой шкалы, соответствующую разным значениям head?

Как обеспечить соответствие цветовой шкалы и цвета в разные строки на График со ссылкой Один цвет = Одно headValue?

Я пытался работать с диаграммой рассеяния, которую удобнее использовать с scalarMappable, но ни одно решение не позволяет мне делать все эти вещи сразу.

1 Ответ

2 голосов
/ 16 апреля 2020

Вот возможный подход. Так как значения '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()

В качестве альтернативы, цвета могут быть назначены с использованием их положения в карте цветов, но без создания

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...