如何在条形图上应用自定义渐变色图?

How to and apply custom gradient colormap on a bar chart?

我是 Matplotlib 的新手,在某些方面仍在苦苦挣扎。

我正在尝试在我的绘图上应用自定义渐变颜色,以根据其在最小和最大范围内的位置填充条形的颜色。

我已经能够生成 LinearSegmentedColormap 并使用 zip 函数创建了一个排序数组,但是,当我尝试将它应用于 color=color=my_cmap(colors_array) 时,它给我一个值错误。

我想知道我的做法是否有问题,或者如果可能的话,还有其他方法可以解决以下问题?

代码:

import math
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(32000, 200000, 3650),
                   np.random.normal(43000, 100000, 3650),
                   np.random.normal(43500, 140000, 3650),
                   np.random.normal(48000, 70000, 3650)],
                  index=[1992, 1993, 1994, 1995])

plt.style.use('ggplot')
fig, ax = plt.subplots()

cmap = mpl.colors.LinearSegmentedColormap.from_list('blue_to_red', ['darkblue', 'darkred'])

df_mean = [df.iloc[index].mean() for index in range(0, len(df.index))]
colors = [color for color in cmap(np.linspace(0, 1, len(df.index)))]
colors = [colors for _ in zip(df_mean, colors)]

ax.bar(
    df.index.tolist(),  # X-Axis, would be 1992 to 1995
    [df.iloc[index].mean() for index in range(0, len(df.index))],  # List of mean values from 92-95
    yerr=[(df.iloc[i].std() / math.sqrt(len(df.iloc[i]))) for i in range(len(df))],  # Standard deviation, 92-95
    color=cmap(colors)
)
fig.colorbar(cmap)

ax.set_title('Voting Results 1992 - 1995', fontsize=12)
plt.xticks(df.index, ('1992', '1993', '1994', '1995'))
ax.set_xlabel('Years')
ax.set_ylabel('Mean')

plt.show()

提前致谢!

首先,将年份作为索引并将所有值放入列中的数据框非常不寻常。 (但是 pandas 可以使用该格式,虽然速度有点慢。)

如果我没理解错的话,您想根据每年的平均值相对于其他年份的平均值分配颜色。您需要创建一个 norm(颜色映射所需的值和范围 0-1 之间的映射)。然后,您可以使用颜色图和该范数将每个均值映射到一种颜色。

年份被转换为字符串,因此 matplotlib 将制作一个分类 x 轴。

这里有一些示例代码可以帮助您入门:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.cm import ScalarMappable

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(32000, 200000, 3650),
                   np.random.normal(43000, 100000, 3650),
                   np.random.normal(43500, 140000, 3650),
                   np.random.normal(48000, 70000, 3650)],
                  index=[1992, 1993, 1994, 1995])
plt.style.use('ggplot')
fig, ax = plt.subplots()

cmap = mpl.colors.LinearSegmentedColormap.from_list('blue_to_red', ['darkblue', 'darkred'])

df_mean = df.mean(axis=1)
norm = plt.Normalize(df_mean.min(), df_mean.max())
colors = cmap(norm(df_mean))

ax.bar(df.index.astype(str),
       df_mean,
       yerr=df.std(axis=1) / np.sqrt(len(df.columns)),
       color=colors)
fig.colorbar(ScalarMappable(cmap=cmap, norm=norm))

ax.set_title('Voting Results 1992 - 1995', fontsize=12)
ax.set_xlabel('Years')
ax.set_ylabel('Mean')
plt.tight_layout()
plt.show()

PS:表示数据框的更标准方法是将每年放入一列中。然后每列的平均值可以计算为 df.mean().

df = pd.DataFrame(np.array([np.random.normal(32000, 200000, 3650),
                            np.random.normal(43000, 100000, 3650),
                            np.random.normal(43500, 140000, 3650),
                            np.random.normal(48000, 70000, 3650)]).T,
                  columns=[1992, 1993, 1994, 1995])
df_mean = df.mean()
ax.bar(df.columns.astype(str),
       df_mean,
       yerr=df.std() / np.sqrt(len(df)),
       color=colors)