从matplotlib中的颜色贴图获取单个颜色

2024-10-03 23:19:21 发布

您现在位置:Python中文网/ 问答频道 /正文

如果您有一个Colormapcmap,例如:

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)

Tags: angetreturnmatplotlib颜色magic地图情况
3条回答

我确实有这个问题,但我需要连续的绘图,以具有高度对比的颜色。我还使用一个包含参考数据的公共子图进行绘图,因此我希望颜色序列能够一致地重复

我最初只是尝试随机生成颜色,在每个绘图之前重新播种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()

生成的绘图可能不是最好的示例,但当以交互方式放大时,它会变得更加相关。 uptime + T-meter

为了得到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

您可以使用下面的代码来实现这一点,您问题中的代码实际上非常接近您所需要的,您所要做的就是调用您拥有的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]的值,它将返回“低于”和“高于”颜色(分别)。默认情况下,这是该范围内的最小和最大颜色(so 0.0和1.0)。可以使用cmap.set_under()cmap.set_over()更改此默认值

对于np.nannp.inf等“特殊”数字,默认值是使用0.0值,可以使用cmap.set_bad()进行更改,类似于上面的“在下”和“在上”

最后,您可能需要规范化数据,使其符合范围[0.0, 1.0]。这可以使用^{}简单地完成,如下面的小示例所示,其中参数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对如何改进答案的建议。)

相关问题 更多 >