将特定的字符串值映射到matplotlib.pyplot.imshow()中的特定颜色 [英] Map a specific string value to a specific color in 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"
}
如果我正在绘制 bar
或 scatter
我可以使用参数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 B
and 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.0
、2.0
、6.0
、7.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屋!