Đặt Dải màu trong matplotlib


156

Tôi có đoạn mã sau:

import matplotlib.pyplot as plt

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

plt.clf()
plt.pcolor(X, Y, v, cmap=cm)
plt.loglog()
plt.xlabel('X Axis')
plt.ylabel('Y Axis')

plt.colorbar()
plt.show()

Vì vậy, điều này tạo ra một biểu đồ của các giá trị 'v' trên các trục X so với Y, sử dụng bản đồ màu được chỉ định. Các trục X và Y là hoàn hảo, nhưng colormap trải đều giữa cực tiểu và cực đại của v. Tôi muốn buộc colormap nằm trong khoảng từ 0 đến 1.

Tôi nghĩ về việc sử dụng:

plt.axis(...)

Để đặt phạm vi của các trục, nhưng điều này chỉ cần các đối số cho min và max của X và Y, chứ không phải colormap.

Biên tập:

Để rõ ràng, giả sử tôi có một biểu đồ có phạm vi giá trị (0 ... 0,3) và một biểu đồ khác có giá trị (0,2 ... 0,8).

Trong cả hai biểu đồ, tôi sẽ muốn phạm vi của thanh màu là (0 ... 1). Trong cả hai biểu đồ, tôi muốn dải màu này giống hệt nhau bằng cách sử dụng toàn bộ phạm vi cdict ở trên (vì vậy 0,25 trong cả hai biểu đồ sẽ có cùng màu). Trong biểu đồ đầu tiên, tất cả các màu trong khoảng từ 0,3 đến 1 sẽ không có trong biểu đồ, nhưng sẽ có trong phím thanh màu ở bên cạnh. Mặt khác, tất cả các màu trong khoảng từ 0 đến 0,2 và từ 0,8 đến 1 sẽ không có trong biểu đồ, nhưng sẽ có trong thanh màu ở bên cạnh.

Câu trả lời:


177

Sử dụng vminvmaxbuộc phạm vi cho màu sắc. Đây là một ví dụ:

nhập mô tả hình ảnh ở đây

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )

def do_plot(n, f, title):
    #plt.clf()
    plt.subplot(1, 3, n)
    plt.pcolor(X, Y, f(data), cmap=cm, vmin=-4, vmax=4)
    plt.title(title)
    plt.colorbar()

plt.figure()
do_plot(1, lambda x:x, "all")
do_plot(2, lambda x:np.clip(x, -4, 0), "<0")
do_plot(3, lambda x:np.clip(x, 0, 4), ">0")
plt.show()

3
Tại sao câu trả lời này tốt hơn câu trả lời sử dụng plt.clim được đăng bởi @Amro?
Alex Lamson

90

Sử dụng hàm CLIM (tương đương với hàm CAXIS trong MATLAB):

plt.pcolor(X, Y, v, cmap=cm)
plt.clim(-4,4)  # identical to caxis([-4,4]) in MATLAB
plt.show()

2
Tôi tin rằng clim () chia tỷ lệ các trục màu, nhưng chính màu sắc thay đổi giá trị. Điểm tại một phần nhất định dọc theo tỷ lệ sẽ có cùng màu với bất kỳ tỷ lệ nào, nhưng giá trị mà nó đại diện sẽ thay đổi.
Paul

4
Đúng. Đây là hành vi mong muốn của người hỏi, vì vậy giải quyết vấn đề: thang màu giống hệt nhau giữa các biểu đồ.
Excalabur

16

Không chắc đây có phải là giải pháp tao nhã nhất (đây là giải pháp tôi đã sử dụng), nhưng bạn có thể chia tỷ lệ dữ liệu của mình trong phạm vi từ 0 đến 1 và sau đó sửa đổi thanh màu:

import matplotlib as mpl
...
ax, _ = mpl.colorbar.make_axes(plt.gca(), shrink=0.5)
cbar = mpl.colorbar.ColorbarBase(ax, cmap=cm,
                       norm=mpl.colors.Normalize(vmin=-0.5, vmax=1.5))
cbar.set_clim(-2.0, 2.0)

Với hai giới hạn khác nhau, bạn có thể kiểm soát phạm vi và chú thích của thanh màu. Trong ví dụ này, chỉ có phạm vi từ -0,5 đến 1,5 được hiển thị trên thanh, trong khi bản đồ màu bao gồm -2 đến 2 (vì vậy đây có thể là phạm vi dữ liệu của bạn, mà bạn ghi lại trước khi chia tỷ lệ).

Vì vậy, thay vì chia tỷ lệ colormap, bạn chia tỷ lệ dữ liệu của mình và điều chỉnh thanh màu theo đó.


1
Tôi nghĩ rằng đó là một điều gì đó rất khác biệt, xin lỗi tôi có lẽ không đủ chính xác trong câu hỏi của tôi. Giải pháp của bạn sẽ chia tỷ lệ màu sắc sao cho những gì được sử dụng để biểu thị giá trị 1.0 sẽ đại diện cho giá trị tối đa trong dữ liệu của tôi. Thanh màu sẽ hiển thị 0..1 khi tôi cần (với vmin = 0, vmax = 1), nhưng mọi thứ trên giá trị tối đa này sẽ có cùng màu ...
Paul

1
... Tôi đã cập nhật câu hỏi của mình để hiển thị những gì tôi đang nói rõ hơn. Xin lỗi nếu tôi quá mơ hồ.
Paul

10

Sử dụng môi trường hình và .set_clim ()

Có thể dễ dàng và an toàn hơn thay thế này nếu bạn có nhiều lô:

import matplotlib as m
import matplotlib.pyplot as plt
import numpy as np

cdict = {
  'red'  :  ( (0.0, 0.25, .25), (0.02, .59, .59), (1., 1., 1.)),
  'green':  ( (0.0, 0.0, 0.0), (0.02, .45, .45), (1., .97, .97)),
  'blue' :  ( (0.0, 1.0, 1.0), (0.02, .75, .75), (1., 0.45, 0.45))
}

cm = m.colors.LinearSegmentedColormap('my_colormap', cdict, 1024)

x = np.arange(0, 10, .1)
y = np.arange(0, 10, .1)
X, Y = np.meshgrid(x,y)

data = 2*( np.sin(X) + np.sin(3*Y) )
data1 = np.clip(data,0,6)
data2 = np.clip(data,-6,0)
vmin = np.min(np.array([data,data1,data2]))
vmax = np.max(np.array([data,data1,data2]))

fig = plt.figure()
ax = fig.add_subplot(131)
mesh = ax.pcolormesh(data, cmap = cm)
mesh.set_clim(vmin,vmax)
ax1 = fig.add_subplot(132)
mesh1 = ax1.pcolormesh(data1, cmap = cm)
mesh1.set_clim(vmin,vmax)
ax2 = fig.add_subplot(133)
mesh2 = ax2.pcolormesh(data2, cmap = cm)
mesh2.set_clim(vmin,vmax)
# Visualizing colorbar part -start
fig.colorbar(mesh,ax=ax)
fig.colorbar(mesh1,ax=ax1)
fig.colorbar(mesh2,ax=ax2)
fig.tight_layout()
# Visualizing colorbar part -end

plt.show()

nhập mô tả hình ảnh ở đây

Một thanh màu

Cách thay thế tốt nhất là sau đó sử dụng một thanh màu duy nhất cho toàn bộ cốt truyện. Có nhiều cách khác nhau để làm điều đó, này hướng dẫn rất hữu ích trong việc tìm hiểu các lựa chọn tốt nhất. Tôi thích giải pháp này mà bạn có thể chỉ cần sao chép và dán thay vì phần colorbar trực quan hóa trước đó của mã.

fig.subplots_adjust(bottom=0.1, top=0.9, left=0.1, right=0.8,
                    wspace=0.4, hspace=0.1)
cb_ax = fig.add_axes([0.83, 0.1, 0.02, 0.8])
cbar = fig.colorbar(mesh, cax=cb_ax)

nhập mô tả hình ảnh ở đây

PS

Tôi sẽ đề nghị sử dụng pcolormeshthay pcolorvì bởi vì nó nhanh hơn (nhiều infos ở đây ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.