我有一个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"
}
如果我正在绘制bar
或scatter
,则可以使用参数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
上面的结果显示在下面的图像中。
#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_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
会获得红色。
答案 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()