2012-01-19 35 views
53

Làm thế nào để thiết lập màu của một dòng trong matplotlib với giá trị vô hướng được cung cấp tại thời gian chạy bằng cách sử dụng một bản đồ màu (nói jet)? Tôi đã thử một vài cách tiếp cận khác nhau ở đây và tôi nghĩ rằng tôi đang bối rối. values[] là một mảng vô số các vết sẹo. các đường cong là một tập hợp các mảng 1-d và các nhãn là một chuỗi các chuỗi văn bản. Mỗi mảng có cùng độ dài.Sử dụng Colormaps để đặt màu của đường kẻ trong matplotlib

fig = plt.figure() 
ax = fig.add_subplot(111) 
jet = colors.Colormap('jet') 
cNorm = colors.Normalize(vmin=0, vmax=values[-1]) 
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) 
lines = [] 
for idx in range(len(curves)): 
    line = curves[idx] 
    colorVal = scalarMap.to_rgba(values[idx]) 
    retLine, = ax.plot(line, color=colorVal) 
    #retLine.set_color() 
    lines.append(retLine) 
ax.legend(lines, labels, loc='upper right') 
ax.grid() 
plt.show() 

Trả lời

66

Lỗi bạn nhận được là do cách bạn xác định jet. Bạn đang tạo lớp cơ sở Colormap với tên 'máy bay phản lực', nhưng điều này rất khác với định nghĩa mặc định của bản đồ 'phản lực'. Lớp cơ sở này sẽ không bao giờ được tạo trực tiếp, và chỉ các lớp con mới được khởi tạo.

Những gì bạn đã tìm thấy với ví dụ của mình là hành vi lỗi trong Matplotlib. Sẽ có một thông báo lỗi rõ ràng hơn được tạo khi mã này được chạy.

Đây là một phiên bản cập nhật của các ví dụ của bạn:

import matplotlib.pyplot as plt 
import matplotlib.colors as colors 
import matplotlib.cm as cmx 
import numpy as np 

# define some random data that emulates your indeded code: 
NCURVES = 10 
np.random.seed(101) 
curves = [np.random.random(20) for i in range(NCURVES)] 
values = range(NCURVES) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
# replace the next line 
#jet = colors.Colormap('jet') 
# with 
jet = cm = plt.get_cmap('jet') 
cNorm = colors.Normalize(vmin=0, vmax=values[-1]) 
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) 
print scalarMap.get_clim() 

lines = [] 
for idx in range(len(curves)): 
    line = curves[idx] 
    colorVal = scalarMap.to_rgba(values[idx]) 
    colorText = (
     'color: (%4.2f,%4.2f,%4.2f)'%(colorVal[0],colorVal[1],colorVal[2]) 
     ) 
    retLine, = ax.plot(line, 
         color=colorVal, 
         label=colorText) 
    lines.append(retLine) 
#added this to get the legend to work 
handles,labels = ax.get_legend_handles_labels() 
ax.legend(handles, labels, loc='upper right') 
ax.grid() 
plt.show() 

Hệ quả là:

enter image description here

Sử dụng một ScalarMappable là một sự cải tiến so với phương pháp trình bày trong câu trả lời liên quan của tôi: creating over 20 unique legend colors using matplotlib

35

Tôi nghĩ sẽ rất có ích khi bao gồm w mũ tôi xem là một phương pháp đơn giản hơn bằng cách sử dụng khoảng trống của numpy kết hợp với đối tượng kiểu cmplotlib của cmplotlib. Có thể giải pháp trên là dành cho phiên bản cũ hơn. Tôi đang sử dụng trăn 3.4.3, matplotlib 1.4.3, và 1.9.1 gumpy, và giải pháp của tôi là như sau.

import matplotlib.pyplot as plt 

from matplotlib import cm 
from numpy import linspace 

start = 0.0 
stop = 1.0 
number_of_lines= 1000 
cm_subsection = linspace(start, stop, number_of_lines) 

colors = [ cm.jet(x) for x in cm_subsection ] 

for i, color in enumerate(colors): 
    plt.axhline(i, color=color) 

plt.ylabel('Line Number') 
plt.show() 

Điều này dẫn đến 1000 dòng có màu duy nhất trải rộng toàn bộ cm.jet như hình dưới đây. Nếu bạn chạy tập lệnh này, bạn sẽ thấy rằng bạn có thể phóng to trên các dòng riêng lẻ.

cm.jet between 0.0 and 1.0 with 1000 graduations

Bây giờ nói rằng tôi muốn 1000 màu đơn hàng của mình chỉ span các phần xanh giữa các dòng 400 đến 600. Tôi chỉ đơn giản là thay đổi bắt đầu của tôi và dừng lại giá trị cho 0,4 và 0,6 và kết quả này trong việc sử dụng chỉ 20% bản đồ màu cm.jet giữa 0,4 và 0,6.

cm.jet between 0.4 and 0.6 with 1000 graduations

Vì vậy, trong một bản tóm tắt một dòng bạn có thể tạo một danh sách các màu rgba từ một matplotlib.cm colormap phù hợp:

colors = [ cm.jet(x) for x in linspace(start, stop, number_of_lines) ] 

Trong trường hợp này tôi sử dụng bản đồ tên là máy bay phản lực thường được gọi nhưng bạn có thể tìm thấy danh sách đầy đủ của colormaps sẵn trong phiên bản matplotlib của bạn bằng cách gọi:

>>> from matplotlib import cm 
>>> dir(cm) 
+0

Điều này chỉ hoạt động vì 'stop' của bạn là 1 – Eric

+1

Tất nhiên 1 là giá trị tốt nhất. Nếu bạn muốn có một dải màu lớn hơn, tất cả những gì bạn cần làm là tăng 'number_of_lines'. Và trong trường hợp bạn chỉ muốn một phần của màu sắc trong ban nhạc bạn giảm 'stop' và tăng' bắt đầu' khi cần thiết. – Parousia

+0

Câu hỏi nhanh: Cách thêm colorbar thay vì chú thích vào cốt truyện của bạn? –

7

Sự kết hợp giữa dòng phong cách, dấu hiệu, và màu sắc chất lượng từ matplotlib:

import itertools 
import matplotlib as mpl 
import matplotlib.pyplot as plt 
N = 8*4+10 
l_styles = ['-','--','-.',':'] 
m_styles = ['','.','o','^','*'] 
colormap = mpl.cm.Dark2.colors # Qualitative colormap 
for i,(marker,linestyle,color) in zip(range(N),itertools.product(m_styles,l_styles, colormap)): 
    plt.plot([0,1,2],[0,2*i,2*i], color=color, linestyle=linestyle,marker=marker,label=i) 
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.,ncol=4); 

enter image description here

Các vấn đề liên quan