簡體   English   中英

從 matplotlib 中的顏色 map 獲取單個 colors

[英]Getting individual colors from a color map in matplotlib

如果您有一個Colormap cmap ,例如:

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

如何在 0 和 1 之間獲得特定顏色,其中 0 是 map 中的第一種顏色,而 1 是 map 中的最后一種顏色?

理想情況下,我可以通過執行以下操作獲得 map 中的中間顏色:

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

你可以用下面的代碼來做到這一點,你的問題中的代碼實際上非常接近你所需要的,你所要做的就是調用你擁有的cmap對象。

import matplotlib

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

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

對於范圍 [0.0, 1.0] 之外的值,它將返回底色和底色(分別)。 默認情況下,這是該范圍內的最小和最大顏色(即 0.0 和 1.0)。 可以使用cmap.set_under()cmap.set_over()更改此默認值。

對於諸如np.nannp.inf之類的“特殊”數字,默認值是使用 0.0 值,這可以使用cmap.set_bad()進行更改,類似於上面的 under 和 over。

最后,您可能需要對數據進行標准化,使其符合范圍[0.0, 1.0] 這可以使用matplotlib.colors.Normalize簡單地完成,如下面的小示例所示,其中參數vminvmax描述應分別映射到 0.0 和 1.0 的數字。

import matplotlib

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

print(norm(15.0)) # 0.5

對數歸一化器 ( matplotlib.colors.LogNorm ) 也可用於具有大范圍值的數據范圍。

(感謝Joe Kingtontcaswell關於如何改進答案的建議。)

為了得到 rgba 整數值而不是浮點值,我們可以這樣做

rgba = cmap(0.5,bytes=True)

因此,為了根據 Ffisegydd 的答案簡化代碼,代碼將如下所示:

#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

我正好有這個問題,但我需要連續的圖來具有高度對比的顏色。 我還使用包含參考數據的公共子圖繪制圖,因此我希望顏色序列始終可重復。

我最初嘗試簡單地隨機生成顏色,在每個繪圖之前重新播種 RNG。 這工作正常(在下面的代碼中注釋掉),但可能會產生幾乎無法區分的顏色。 我想要高度對比的顏色,最好從包含所有顏色的顏色圖中采樣。

我可以在一個圖中擁有多達 31 個數據系列,因此我將顏色圖分成了許多步驟。 然后我按順序走幾步,確保我不會很快回到給定顏色的附近。

我的數據是一個非常不規則的時間序列,所以我想查看點和線,點的顏色與線的“相反”。

鑒於上述所有內容,最容易生成帶有相關參數的字典以繪制單個系列,然后將其擴展為調用的一部分。

這是我的代碼。 也許不漂亮,但實用。

from matplotlib import cm
cmap = cm.get_cmap('gist_rainbow')  #('hsv') #('nipy_spectral')

max_colors = 31   # Constant, max mumber of series in any plot.  Ideally prime.
color_number = 0  # Variable, incremented for each series.

def restart_colors():
    global color_number
    color_number = 0
    #np.random.seed(1)

def next_color():
    global color_number
    color_number += 1
    #color = tuple(np.random.uniform(0.0, 0.5, 3))
    color = cmap( ((5 * color_number) % max_colors) / max_colors )
    return color

def plot_args():  # Invoked for each plot in a series as: '**(plot_args())'
    mkr = next_color()
    clr = (1 - mkr[0], 1 - mkr[1], 1 - mkr[2], mkr[3])  # Give line inverse of marker color
    return {
        "marker": "o",
        "color": clr,
        "mfc": mkr,
        "mec": mkr,
        "markersize": 0.5,
        "linewidth": 1,
    }

我的上下文是 JupyterLab 和 Pandas,所以這里是示例繪圖代碼:

restart_colors()  # Repeatable color sequence for every plot

fig, axs = plt.subplots(figsize=(15, 8))
plt.title("%s + T-meter"%name)

# Plot reference temperatures:
axs.set_ylabel("°C", rotation=0)
for s in ["T1", "T2", "T3", "T4"]:
    df_tmeter.plot(ax=axs, x="Timestamp", y=s, label="T-meter:%s" % s, **(plot_args()))

# Other series gets their own axis labels
ax2 = axs.twinx()
ax2.set_ylabel(units)

for c in df_uptime_sensors:
    df_uptime[df_uptime["UUID"] == c].plot(
        ax=ax2, x="Timestamp", y=units, label="%s - %s" % (units, c), **(plot_args())
    )

fig.tight_layout()
plt.show()

結果圖可能不是最好的例子,但當交互式放大時它變得更加相關。 正常運行時間 + T-meter

為了建立在Ffisegyddamaliammr的解決方案的基礎上,以下是我們為自定義顏色圖制作 CSV 表示的示例:

#! /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]))

我曾經遇到過類似的情況,我需要“n”不。 顏色圖中的顏色,以便我可以將每種顏色分配給我的數據。 我在一個名為“ mycolorpy ”的包中為此編譯了一個代碼。 您可以使用以下命令 pip 安裝它:

pip install mycolorpy

然后你可以這樣做:

from mycolorpy import colorlist as mcp
import numpy as np

示例:從“winter”營創建一個包含 5 個十六進制字符串的列表

color1=mcp.gen_color(cmap="winter",n=5)
print(color1)

輸出:

['#0000ff', '#0040df', '#0080bf', '#00c09f', '#00ff80']

另一個從 Camp bwr 生成 16 種顏色列表的示例:

color2=mcp.gen_color(cmap="bwr",n=16)
print(color2)

輸出:

['#0000ff', '#2222ff', '#4444ff', '#6666ff', '#8888ff', '#aaaaff', '#ccccff', '#eeeeff', '#ffeeee', '#ffcccc', '#ffaaaa', '#ff8888', '#ff6666', '#ff4444', '#ff2222', '#ff0000']

有一個帶有使用示例的python 筆記本,可以更好地可視化這一點。

假設您想從標准化為給定數據的 cmap 生成顏色列表。 你可以使用:

a=random.randint(1000, size=(200))
a=np.array(a)
color1=mcp.gen_color_normalized(cmap="seismic",data_arr=a)
plt.scatter(a,a,c=color1)

輸出: 在此處輸入圖片說明

您還可以使用以下方法反轉顏色:

color1=mcp.gen_color_normalized(cmap="seismic",data_arr=a,reverse=True)
plt.scatter(a,a,c=color1)

輸出: 在此處輸入圖片說明

顏色圖帶有自己的歸一化方法,因此如果您已經繪制了繪圖,則可以訪問特定值的顏色。

import matplotlib.pyplot as plt
import numpy as np

cmap = plt.cm.viridis

cm = plt.pcolormesh(np.random.randn(10, 10), cmap=cmap)

print(cmap(cm.norm(2.2)))

為了快速而骯臟,您可以直接使用 map。 或者你可以按照@amaliammr 所說的去做。

data_size = 23   # range 0..23
colors = plt.cm.turbo
color_normal = colours.N/data_size

for i in range(data_size):
    col = colours.colors[int(i*color_normal)]


如果您有 Colormap cmap ,例如:

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

如何從 0 到 1 之間獲取特定顏色,其中 0 是地圖中的第一種顏色,而 1 是地圖中的最后一種顏色?

理想情況下,我可以通過執行以下操作獲得地圖中的中間顏色:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM