将特定的字符串值映射到matplotlib.pyplot.imshow()

时间:2018-09-11 20:48:49

标签: python matplotlib

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

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()绘制此图像,并指定以下颜色图:

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

如果我正在绘制barscatter,则可以使用参数color=a_list_of_colors进行调用,但这不适用于imshow()

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

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

    from matplotlib.colors import ListedColormap 

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

但是还有更好的方法吗?


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

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

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

series基本上是这样的:

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

我的df中的第五个元素是B,当我打印custom_cmap.__dict__.colors[4]时,我得到#83DF39,它与我的{{ 1}}。因此,映射是正确的。

当我用B调用df时会出现问题,因为它没有跟随plt.imshow() -某些值的颜色错误。

我的第一个想法是我弄乱了顺序,这意味着cmap=custom_cmap并不遵循cmap的顺序,但是确实遵循。{p>

上面的color_list包含18个值,而color_list也包含18个值。 df中的最后一个值是df,这意味着df中的最后一个颜色应该是F


添加更多代码。

color_list

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

enter image description here

  • 请注意,此图片中的数据与原始帖子中的#52BFEC中的数据不同。

我测试了另一个# 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')

df

但是颜色仍然无法正确映射。通过这些颜色,color_dictcolor_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.0和某些6.0会获得红色。

1 个答案:

答案 0 :(得分:1)

很难看到所提议的代码出了什么问题而又无法自行运行。

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

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()

enter image description here