Colormap ngược trong matplotlib


252

Tôi muốn biết làm thế nào để đơn giản đảo ngược thứ tự màu của một bản đồ màu đã cho để sử dụng nó với plot_surface.

Câu trả lời:


463

Các bản đồ màu tiêu chuẩn cũng có phiên bản đảo ngược. Họ có cùng tên với cách _rgiải quyết đến cùng. ( Tài liệu ở đây. )


Điều này không hoạt động với "amfhot": "ValueError: Colormap amfhot_r không được công nhận". Tôi cho rằng "hot_r" sẽ phải đủ.
shockburner

Tương tự, "ValueError: Colormap red_r không được nhận dạng."
Alex Willison

18

Trong matplotlib, một bản đồ màu không phải là một danh sách, nhưng nó chứa danh sách các màu của nó như colormap.colors. Và mô-đun matplotlib.colorscung cấp một chức năng ListedColormap()để tạo một bản đồ màu từ một danh sách. Vì vậy, bạn có thể đảo ngược bất kỳ bản đồ màu bằng cách làm

colormap_r = ListedColormap(colormap.colors[::-1])

7
+1. Tuy nhiên, điều này sẽ không đảo ngược bất kỳ colormap. Chỉ ListedColormaps (nghĩa là rời rạc, thay vì nội suy) có colorsthuộc tính. Đảo ngược LinearSegmentedColormapsphức tạp hơn một chút. (Bạn cần đảo ngược mọi mục trong _segmentdatadict.)
Joe Kington

3
Về việc đảo ngược LinearSegmentedColormaps, tôi chỉ làm điều này cho một số màu. Đây là một IPython Notebook về nó.
kwinkunks

@kwinkunks Tôi nghĩ rằng chức năng trong sổ ghi chép của bạn không đúng, xem câu trả lời bên dưới
Mattijn

14

Giải pháp khá đơn giản. Giả sử bạn muốn sử dụng lược đồ màu "mùa thu". Phiên bản tiêu chuẩn:

cmap = matplotlib.cm.autumn

Để đảo ngược phổ màu colormap, hãy sử dụng hàm get_cmap () và nối '_r' vào tiêu đề colormap như thế này:

cmap_reversed = matplotlib.cm.get_cmap('autumn_r')

bạn có thể cung cấp liên kết tài liệu nơi bạn có .autumn từ đâu không?
Xitcod13 ngày

Điều này có thể bị hỏng sau ... matplotlib.org/3.1.1/gallery/color/colormap_Vference.html , nhưng tôi chắc chắn rằng bất kỳ ai quan tâm sẽ có thể tìm thấy điều này bằng cách tìm kiếm nào.
Jlanger

13

LinearSegmentedColormapsdựa trên một từ điển màu đỏ, xanh lá cây và xanh dương, nên cần phải đảo ngược từng mục:

import matplotlib.pyplot as plt
import matplotlib as mpl
def reverse_colourmap(cmap, name = 'my_cmap_r'):
    """
    In: 
    cmap, name 
    Out:
    my_cmap_r

    Explanation:
    t[0] goes from 0 to 1
    row i:   x  y0  y1 -> t[0] t[1] t[2]
                   /
                  /
    row i+1: x  y0  y1 -> t[n] t[1] t[2]

    so the inverse should do the same:
    row i+1: x  y1  y0 -> 1-t[0] t[2] t[1]
                   /
                  /
    row i:   x  y1  y0 -> 1-t[n] t[2] t[1]
    """        
    reverse = []
    k = []   

    for key in cmap._segmentdata:    
        k.append(key)
        channel = cmap._segmentdata[key]
        data = []

        for t in channel:                    
            data.append((1-t[0],t[2],t[1]))            
        reverse.append(sorted(data))    

    LinearL = dict(zip(k,reverse))
    my_cmap_r = mpl.colors.LinearSegmentedColormap(name, LinearL) 
    return my_cmap_r

Xem nó hoạt động:

my_cmap        
<matplotlib.colors.LinearSegmentedColormap at 0xd5a0518>

my_cmap_r = reverse_colourmap(my_cmap)

fig = plt.figure(figsize=(8, 2))
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15])
norm = mpl.colors.Normalize(vmin=0, vmax=1)
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = my_cmap, norm=norm,orientation='horizontal')
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = my_cmap_r, norm=norm, orientation='horizontal')

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

BIÊN TẬP


Tôi không nhận được bình luận của user3445587. Nó hoạt động tốt trên colormap cầu vồng:

cmap = mpl.cm.jet
cmap_r = reverse_colourmap(cmap)

fig = plt.figure(figsize=(8, 2))
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15])
norm = mpl.colors.Normalize(vmin=0, vmax=1)
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = cmap, norm=norm,orientation='horizontal')
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = cmap_r, norm=norm, orientation='horizontal')

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

Nhưng nó đặc biệt hoạt động tốt cho các bản đồ được khai báo tùy chỉnh, vì không có mặc định _rcho bản đồ màu được khai báo tùy chỉnh. Ví dụ sau được lấy từ http://matplotlib.org/examples/pylab_examples/custom_cmap.html :

cdict1 = {'red':   ((0.0, 0.0, 0.0),
                   (0.5, 0.0, 0.1),
                   (1.0, 1.0, 1.0)),

         'green': ((0.0, 0.0, 0.0),
                   (1.0, 0.0, 0.0)),

         'blue':  ((0.0, 0.0, 1.0),
                   (0.5, 0.1, 0.0),
                   (1.0, 0.0, 0.0))
         }

blue_red1 = mpl.colors.LinearSegmentedColormap('BlueRed1', cdict1)
blue_red1_r = reverse_colourmap(blue_red1)

fig = plt.figure(figsize=(8, 2))
ax1 = fig.add_axes([0.05, 0.80, 0.9, 0.15])
ax2 = fig.add_axes([0.05, 0.475, 0.9, 0.15])

norm = mpl.colors.Normalize(vmin=0, vmax=1)
cb1 = mpl.colorbar.ColorbarBase(ax1, cmap = blue_red1, norm=norm,orientation='horizontal')
cb2 = mpl.colorbar.ColorbarBase(ax2, cmap = blue_red1_r, norm=norm, orientation='horizontal')

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


Ví dụ này không đầy đủ theo nghĩa là phân đoạn không nằm trong danh sách nên không thể đảo ngược (ví dụ như cầu vồng tiêu chuẩn). Tôi nghĩ về nguyên tắc tất cả các tuyến tính tuyến tính có thể đảo ngược được bằng cách sử dụng hàm lambda như trong bản đồ màu cầu vồng?
ở nước ngoài

@ user3445587 Tôi thêm một số ví dụ khác, nhưng tôi nghĩ nó chỉ hoạt động tốt trên bản đồ màu cầu vồng tiêu chuẩn
Mattijn

Vì nó quá dài, tôi đã thêm một câu trả lời mới, nó sẽ hoạt động cho tất cả các loại linearSegmentData. Vấn đề là đối với cầu vồng, _seributiondata được thực hiện khác nhau. Vì vậy, mã của bạn - ít nhất là trên máy của tôi - không hoạt động với bản đồ màu cầu vồng.
ở nước ngoài

12

Kể từ Matplotlib 2.0, có một reversed()phương thức cho ListedColormapLinearSegmentedColorMapcác đối tượng, vì vậy bạn chỉ có thể làm

cmap_reversed = cmap.reversed()

Đây là tài liệu.


1

Có hai loại linearSegmentedColormaps. Trong một số, _seributiondata được đưa ra một cách rõ ràng, ví dụ, cho máy bay phản lực:

>>> cm.jet._segmentdata
{'blue': ((0.0, 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65, 0, 0), (1, 0, 0)), 'red': ((0.0, 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), (1, 0.5, 0.5)), 'green': ((0.0, 0, 0), (0.125, 0, 0), (0.375, 1, 1), (0.64, 1, 1), (0.91, 0, 0), (1, 0, 0))}

Đối với cầu vồng, _seributiondata được đưa ra như sau:

>>> cm.rainbow._segmentdata
{'blue': <function <lambda> at 0x7fac32ac2b70>, 'red': <function <lambda> at 0x7fac32ac7840>, 'green': <function <lambda> at 0x7fac32ac2d08>}

Chúng ta có thể tìm thấy các hàm trong nguồn matplotlib, nơi chúng được đưa ra là

_rainbow_data = {
        'red': gfunc[33],   # 33: lambda x: np.abs(2 * x - 0.5),
        'green': gfunc[13], # 13: lambda x: np.sin(x * np.pi),
        'blue': gfunc[10],  # 10: lambda x: np.cos(x * np.pi / 2)
}

Mọi thứ bạn muốn đã được thực hiện trong matplotlib, chỉ cần gọi cm.revcmap, đảo ngược cả hai loại phân đoạn, vì vậy

cm.revcmap(cm.rainbow._segmentdata)

nên thực hiện công việc - bạn chỉ cần tạo một linearSegmentData mới từ đó. Trong revcmap, việc đảo ngược chức năng dựa trên SegmentData được thực hiện với

def _reverser(f):
    def freversed(x):
        return f(1 - x)
    return freversed

trong khi các danh sách khác được đảo ngược như bình thường

valnew = [(1.0 - x, y1, y0) for x, y0, y1 in reversed(val)] 

Vì vậy, thực sự tất cả những gì bạn muốn, là

def reverse_colourmap(cmap, name = 'my_cmap_r'):
     return mpl.colors.LinearSegmentedColormap(name, cm.revcmap(cmap._segmentdata)) 

1

Không có cách dựng sẵn (chưa) đảo ngược các bản đồ màu tùy ý, nhưng một giải pháp đơn giản là thực sự không sửa đổi thanh màu mà tạo ra một đối tượng Bình thường hóa đảo ngược:

from matplotlib.colors import Normalize

class InvertedNormalize(Normalize):
    def __call__(self, *args, **kwargs):
        return 1 - super(InvertedNormalize, self).__call__(*args, **kwargs)

Sau đó, bạn có thể sử dụng plot_surfacechức năng này với và các hàm vẽ đồ thị Matplotlib khác bằng cách thực hiện, ví dụ:

inverted_norm = InvertedNormalize(vmin=10, vmax=100)
ax.plot_surface(..., cmap=<your colormap>, norm=inverted_norm)

Điều này sẽ làm việc với bất kỳ colormap Matplotlib.


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.