将特定的字符串值映射到matplotlib.pyplot.imshow()中的特定颜色 [英] Map a specific string value to a specific color in matplotlib.pyplot.imshow()

查看:82
本文介绍了将特定的字符串值映射到matplotlib.pyplot.imshow()中的特定颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 pandas.dataframe 看起来像这样:

I have a pandas.dataframe that looks like this:

columns    0    1   2   3   4   5
           A    A   A   A   B   B
           B    B   B   C   C   D
           D    D   E   E   F   F

我想使用 pyplot.imshow() 绘制此图,指定以下颜色图:

I want to plot this using pyplot.imshow(), specifying the following colormap:

color_dict = {
    "A": "#DA291E",
    "B": "#83DF39",
    "C": "#E8132d",
    "D": "#008933",
    "E": "#006CB3",
    "F": "#52BFEC"
}

如果我正在绘制 barscatter 我可以使用参数color=a_list_of_colors 调用,但这不起作用imshow().

If I was plotting a bar or a scatter I could just call with the argumentcolor=a_list_of_colors but this doesn't work with imshow().

相反,我需要使用 cmap 进行调用,但据我所知,无法创建将特定颜色映射到值的 cmap.

Instead I need to call with a cmap but as far as I understand it isn´t possible to create a cmap where a specific color is mapped to a value.

这意味着我需要像这样创建一个颜色图:

This means I need to create a colormap like this:

    from matplotlib.colors import ListedColormap 

    _colors = ["#DA291E", "DA291E", "DA291E", "DA291E" 
               "#83DF39", "#83DF39", "#83DF39", "#83DF39", "#83DF39", #...and so on]
    cmap = ListedColormap(_colors, name="custom_cmap")

但是有没有更好的方法来解决这个问题?

But is there a better way to go about this?

我以为我可以实现上面的方法,但是由于某种原因它不起作用,而且我似乎也找不到原因.

I thought I could implement above method but for some reason it doesn't work and I can't seem to figure out why.

我首先根据上面的 df 的长 series 版本创建一个color_list,然后将该列表转换为颜色图:

I begin by creating a color_list based on a long series version of my df above and then convert that list to a colormap:

color_list = list(series.map(color_dict))
custom_cmap = ListedColormap(color_list, name="custom_cmap")

长的系列基本上是这样的:

A
A
A
A
B
B
B
B
B
C
#...and so on

我的 df 中的第五个元素是 B ,当我打印 custom_cmap .__ dict __.colors [4] 时,我得到的#83DF39 对应于我的 df 中的字符串值 B.因此,映射是正确的.

The fifth element in my df is Band when I print custom_cmap.__dict__.colors[4] I get #83DF39 which corresponds with the string value B in my df. So the mapping is correct.

当我使用 cmap=custom_cmap 调用 plt.imshow() 时出现问题,因为它不遵循 cmap - 一些值得到错误的颜色.

The problem occurs when I call plt.imshow() with cmap=custom_cmap as it doesn´t follow the cmap - some values get the wrong color.

我的第一个想法是我弄乱了顺序,这意味着 color_list 没有遵循 df 的顺序,但确实如此.

My first thought was that I had messed up the order meaning that the color_list didn´t follow the order of the df but it does.

上面的 df 包含18个值,而color_list也包含18个值. df 中的最后一个值是 F ,这意味着 color_list 中的最后一个颜色应为#52BFEC ,它是.

The df above contains 18 values and the color_list does too. The last value in the df is an F which means that the last color in the color_list should be #52BFEC, which it is.

添加更多代码.

# Begin by converting strings to any number since plt.imshow() needs numbers
float_dict = {
    'A': 0.0,
    'B': 1.0,
    'C': 2.0,
    'D': 3.0,
    'E': 4.0,
    'F': 5.0,
    'G': 6.0,
    'H': 7.0,
    'I': 8.0
}

converted_series = series.map(float_dict).copy()

# Map each float to a specific color
color_dict = {
    0.0: '#DA291E',
    1.0: '#E7112d',
    2.0: '#83CD39',
    3.0: '#009934',
    4.0: '#007AB3',
    5.0: '#54BDEC',
    6.0: '#000066',
    7.0: '#DDDD11',
    8.0: '#572B84',
}

# Create a cmap from a color list
color_list = list(converted_series.map(color_dict))
custom_cmap = ListedColormap(color_list, name="custom_cmap")

# Widen the series into a df
df = series_to_wide_df(converted_series, n_columns=8)

# Plot it
plt.imshow(df, cmap=custom_cmap, interpolation='none')

上面的结果显示在下面的图像中.

The result of above is seen in image below.

  • 请注意,此图像中的数据与原始帖子中 df 中的数据不同.
  • Note that the data in this image is not the same the data in the df in the original post.

我测试了另一种 color_dict :

color_dict = {
    0.0: '#FF0000',
    1.0: '#FF0000',
    2.0: '#FF0000',
    3.0: '#FF0000',
    4.0: '#FF0000',
    5.0: '#000000',
    6.0: '#000000',
    7.0: '#000000',
    8.0: '#000000'
}

但是颜色仍然无法正确映射.有了这些颜色,1.02.06.07.0 和一些 8.0 得到红色.

But the colors still don't map correctly. With these colors, 1.0, 2.0, 6.0, 7.0 and some 8.0 get the color red.

推荐答案

如果代码不能自行运行,就很难看出建议的代码哪里出错了.

It's rather hard to see where the proposed code goes wrong without it being runnable by itself.

以下将创建一个将字母映射到数字的字典并将其应用于数据帧.然后它将创建一个颜色图,颜色与数据框中(可能的)值一样多.然后,当色图在零和色图中的元素数量之间进行归一化时,使用imshow进行打印就可以正常工作.(如果并非所有可能的值都实际出现在要绘制的特定数据框中,例如在字母 A 和 H 将丢失的情况下,这种归一化可能很有用.)

The following would create a dictionary mapping letters to numbers and apply it to the dataframe. Then it'll create a colormap with as many colors as there are (possible) values in the dataframe. Then plotting with imshow works fine when the colormap is normalized between zero and the number of elements in the colormap. (This normalization may just be useful if not all possible values actually occur in the specific dataframe to plot, e.g. in the case letters A and H would be missing.)

import numpy as np; np.random.seed(42)
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap


df = pd.DataFrame(np.random.choice(list("ABCDEFGH"), size=(8,8)))
print(df)

#mapping from letters to numbers
letter2num = dict(zip(list("ABCDEFGH"), np.arange(8)))
df2 = pd.DataFrame(np.array( [letter2num[i] for i in df.values.flat] ).reshape(df.shape))


#produce colormap with as many colors as there are unique values in df
colors = ["pink", "red", "violet", "blue", 
          "turquoise", "limegreen", "gold", "brown"]  # use hex colors here, if desired.
cmap = ListedColormap(colors)

fig, ax = plt.subplots()
ax.imshow(df2.values, vmin=0, vmax=len(cmap.colors), cmap=cmap)


for i in range(len(df2)):
    for j in range(len(df2.columns)):
        ax.text(j,i, df.values[i,j], ha="center", va="center")
plt.show()

这篇关于将特定的字符串值映射到matplotlib.pyplot.imshow()中的特定颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆