Lấy màu riêng lẻ từ bản đồ màu trong matplotlib


136

Nếu bạn có Colormap cmap, ví dụ:

cmap = matplotlib.cm.get_cmap('Spectral')

Làm thế nào bạn có thể có được một màu cụ thể trong số đó từ 0 đến 1, trong đó 0 là màu đầu tiên trong bản đồ và 1 là màu cuối cùng trong bản đồ?

Lý tưởng nhất là tôi có thể lấy màu giữa trong bản đồ bằng cách thực hiện:

>>> do_some_magic(cmap, 0.5) # Return an RGBA tuple
(0.1, 0.2, 0.3, 1.0)

Câu trả lời:


219

Bạn có thể làm điều này với mã bên dưới và mã trong câu hỏi của bạn thực sự rất gần với những gì bạn cần, tất cả những gì bạn phải làm là gọi cmapđối tượng bạn có.

import matplotlib

cmap = matplotlib.cm.get_cmap('Spectral')

rgba = cmap(0.5)
print(rgba) # (0.99807766255210428, 0.99923106502084169, 0.74602077638401709, 1.0)

Đối với các giá trị nằm ngoài phạm vi [0,0, 1,0], nó sẽ trả về màu dưới và trên (tương ứng). Theo mặc định, đây là màu tối thiểu và tối đa trong phạm vi (vì vậy 0,0 và 1,0). Mặc định này có thể được thay đổi với cmap.set_under()cmap.set_over().

Đối với các số "đặc biệt" như np.nannp.infmặc định là sử dụng giá trị 0,0, điều này có thể được thay đổi bằng cách sử dụng cmap.set_bad()tương tự như dưới và trên như trên.

Cuối cùng, có thể bạn cần bình thường hóa dữ liệu của mình sao cho phù hợp với phạm vi [0.0, 1.0]. Điều này có thể được thực hiện bằng cách sử dụng matplotlib.colors.Normalizeđơn giản như được hiển thị trong ví dụ nhỏ bên dưới, nơi các đối số vminvmaxmô tả các số nào sẽ được ánh xạ thành 0,0 và 1,0 tương ứng.

import matplotlib

norm = matplotlib.colors.Normalize(vmin=10.0, vmax=20.0)

print(norm(15.0)) # 0.5

Một trình chuẩn hóa logarit ( matplotlib.colors.LogNorm ) cũng có sẵn cho các phạm vi dữ liệu với phạm vi giá trị lớn.

(Cảm ơn cả Joe Kingtontcaswell vì những gợi ý về cách cải thiện câu trả lời.)


3
Trên thực tế, đối với các giá trị nhỏ hơn 0 hoặc nhiều hơn 1, nó sẽ trả về màu "trên" hoặc "dưới". Theo mặc định, đó là màu ở dưới cùng / trên cùng của bản đồ màu, nhưng không thể thay đổi. Ví dụ: cmap.set_under('red'); print cmap(0.0), cmap(-0.01)
Joe Kington

Xin chào @Joe, cảm ơn vì đã sửa, tôi đã sửa đổi câu trả lời của mình :)
Ffisegydd

Ngoài ra còn set_badcó định nghĩa những gì trong np.nanvà cho np.infiirc. Bạn nên đề cập đến các Normalizephương pháp ở đây là tốt.
tacaswell

11
Thông tin rất hữu ích và tại sao trên trái đất không thể tìm thấy điều này trong tài liệu!?!
Jaap Elder

9
Nếu điều này không hiệu quả với bất kỳ ai và bạn thấy module 'matplotlib' has no attribute 'cm', hãy thử thay thế hai dòng đầu tiên bằngimport matplotlib.pyplot as plt; cmap = plt.cm.get_cmap('Spectral')
Ẩn danh

9

Để có được giá trị số nguyên rgba thay vì giá trị float, chúng ta có thể làm

rgba = cmap(0.5,bytes=True)

Vì vậy, để đơn giản hóa mã dựa trên câu trả lời từ Ffisegydd, mã sẽ như thế này:

#import colormap
from matplotlib import cm

#normalize item number values to colormap
norm = matplotlib.colors.Normalize(vmin=0, vmax=1000)

#colormap possible values = viridis, jet, spectral
rgba_color = cm.jet(norm(400),bytes=True) 

#400 is one of value between 0 and 1000

0

Để xây dựng các giải pháp từ Ffisegyddamaliammr , đây là một ví dụ nơi chúng tôi tạo đại diện CSV cho một bản đồ màu tùy chỉnh:

#! /usr/bin/env python3
import matplotlib
import numpy as np 

vmin = 0.1
vmax = 1000

norm = matplotlib.colors.Normalize(np.log10(vmin), np.log10(vmax))
lognum = norm(np.log10([.5, 2., 10, 40, 150,1000]))

cdict = {
    'red':
    (
        (0., 0, 0),
        (lognum[0], 0, 0),
        (lognum[1], 0, 0),
        (lognum[2], 1, 1),
        (lognum[3], 0.8, 0.8),
        (lognum[4], .7, .7),
    (lognum[5], .7, .7)
    ),
    'green':
    (
        (0., .6, .6),
        (lognum[0], 0.8, 0.8),
        (lognum[1], 1, 1),
        (lognum[2], 1, 1),
        (lognum[3], 0, 0),
        (lognum[4], 0, 0),
    (lognum[5], 0, 0)
    ),
    'blue':
    (
        (0., 0, 0),
        (lognum[0], 0, 0),
        (lognum[1], 0, 0),
        (lognum[2], 0, 0),
        (lognum[3], 0, 0),
        (lognum[4], 0, 0),
    (lognum[5], 1, 1)
    )
}


mycmap = matplotlib.colors.LinearSegmentedColormap('my_colormap', cdict, 256)   
norm = matplotlib.colors.LogNorm(vmin, vmax)
colors = {}
count = 0
step_size = 0.001
for value in np.arange(vmin, vmax+step_size, step_size):
    count += 1
    print("%d/%d %f%%" % (count, vmax*(1./step_size), 100.*count/(vmax*(1./step_size))))
    rgba = mycmap(norm(value), bytes=True)
    color = (rgba[0], rgba[1], rgba[2])
    if color not in colors.values():
        colors[value] = color

print ("value, red, green, blue")
for value in sorted(colors.keys()):
    rgb = colors[value]
    print("%s, %s, %s, %s" % (value, rgb[0], rgb[1], rgb[2]))

0

Để hoàn thiện đây là những lựa chọn cmap tôi gặp phải cho đến nay:

Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, BuRn_r, BuPu, BuPu_r, CMRmap, CMRmap_r, Dark2, DarkR_rrrrrrrrrrrrrrrrrrrrrrrrr PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG_r, PuBuGn, PuBuGn_r, PuBu_r, trát, trêu, rủ rê RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, RdYlGn, RdYlGn_r, Reds_r, Set1, Set1_rrrrrrrrn afmhot_r, mùa thu, mùa thu, nhị phân, nhị phân, nhị phân, xương, xương_r, brg, brg_r, xương, xương, xương, cờ, cờ, cờgist_g, như thế nào đó là có thể như vậy, có thể như vậy, có sự gia tăng như vậy như thế nào jet_r, magma, magma_r, nipy_spectral, mùa xuân, mùa xuân, mùa xuân, mùa xuân, mùa hè, mùa xuân, mùa xuân, mùa xuân, mùa xuân, mùa xuân tab20b, tab20b_r, tab20c, tab20c_r, địa hình, địa hình_r, hoàng hôn, twilight_r, twilight_shifted, twilight_shifted_r, viridis, viridis_r, mùa đông, winter_rgrey_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, màu hồng, màu hồng, màu hồng mùa xuân, spring_r, mùa hè, mùa hègrey_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, màu hồng, màu hồng, màu hồng mùa xuân, spring_r, mùa hè, mùa hèviridis, viridis_r, mùa đông, winter_rviridis, viridis_r, mùa đông, winter_r

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.