基于值的Matplotlib条形图颜色化

21

有没有一种方法可以根据条形图的值对条形进行着色。例如:

- values below -0.5: red
- values between -0.5 to 0: green
- values between 0 to 08: blue
- etc

我找到了一些基本的柱状图颜色示例,但没有适用于值范围(例如上面的示例)的内容。

更新:

感谢kikocorreoso提出的建议。当两个轴都是数字时,您的示例非常有效。 但是,在我的情况下,我的原始数据结构是一个pandas数据框。 然后我使用df.stack()并绘制结果。 这意味着数据帧的行/列成为绘图的x轴,数据帧单元格成为Y轴(柱形)。

我尝试过如您所述的掩码,但似乎在Y轴为数字而X轴为名称时不起作用。例如:

     col1    col2   col3   col4
 row1 1       2      3      4
 row2 5       6      7      8
 row3 9       10     11     12
 row4 13      14     15     16

需要将上述数据框绘制为条形图,行/列组合形成x轴。每个单元格的值将成为一根条。最终,按照原始问题着色这些条。谢谢。

5个回答

39

您可以为数据集使用掩码。一个基本的示例可能是以下内容:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(10)
y = np.arange(10) * 0.1

mask1 = y < 0.5
mask2 = y >= 0.5

plt.bar(x[mask1], y[mask1], color = 'red')
plt.bar(x[mask2], y[mask2], color = 'blue')
plt.show()

结果应该是:enter image description here

更新:

由于您更新了问题,我也对代码进行了更新。对于您的简单情况,如果我理解正确,您可以使用以下(丑陋的)hack方法:

import pandas as pd

df = pd.DataFrame({'col1':[1,2,3], 'col2':[4,5,6]}, 
                  index = ['row1','row2','row3'])

dfstacked = df.stack()

mask = dfstacked <= 3

colors = np.array(['b']*len(dfstacked))
colors[mask.values] = 'r'

dfstacked.plot(kind = 'bar', rot = 45, color = colors)
plt.show()

或者使用更加面向对象的解决方案

代码简要说明:

  • 我为我的红色列创建了一个掩码
  • 我创建了一个颜色数组
  • 更改颜色数组,以便对我的掩码值使用其他颜色
  • 由于 dfstacked 数据帧具有 MultiIndex,所以刻度不会被正确打印,因此我使用 rot 关键字进行旋转。如果您想自动化获取漂亮的图形,可以在 plt.show() 之前使用 plt.tight_layout()

希望能对您有所帮助。


抱歉回复晚了。这看起来很不错,但是当一个轴是名称列表而不是数字时,我好像无法让它工作。我已经用更多的细节编辑了最初的问题。如果您有解决方案,请发布更新。 - darkpool

11

我看到这个问题很久以前就被问过了,但以防万一能帮到有人的话,这就是对我有效的做法:

遍历所有值并根据自定义条件将颜色附加到列表中,因此您得到的是一个具有与值数量相同的颜色规范的列表;然后在plt.bar()中使用颜色列表:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(10)
y = np.arange(10) * 0.1

col = []
for val in y:
    if val < 0.4:
        col.append('blue')
    elif val >= 0.7:
        col.append('green')
    else:
        col.append('red')

# col looks like this: ['blue', 'blue', 'blue', 'blue', 'red', 'red', 'red', 'green', 'green', 'green']

plt.bar(x, y, color = col)


6

使用列表解析和条件表达式:

profit_color = [('green' if p > 0 else 'red') for p in profit]

plt.bar(year, profit, color=profit_color)

带有值范围的完整示例:

import matplotlib.pyplot as plt

profit = [-4.56, -0.81, -0.47, 0.25, 1.05, 1.93, 2.91, 3.43]
year = [*range(len(profit))]

profit_color = [{p<0: 'red', 0<=p<=2: 'orange', p>2: 'green'}[True] for p in profit]

plt.bar(year, profit, color=profit_color)
plt.show()

输出结果: 基于颜色的柱状图


1

对上面的答案进行了小改进


x = np.arange(4)

y = np.array([-2,3,-1,2])

cc=list(map(lambda x: 'red' if x <= 0 else 'blue', y))

plt.bar(x, y, color = cc)
plt.show()

如果您想对答案进行补充,请考虑在答案下方发表评论。 - ygorg

1
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(4)
y = np.array([-2,3,-1,2])
cc=['colors']*len(y)
for n,val in enumerate(y):
    if val<0:
        cc[n]='red'
    elif val>=0
        cc[n]='blue'

plt.bar(x, y, color = cc)
plt.show()

enter image description here


这感觉像是一个非常直接和易于理解的方法,我可以一遍又一遍地使用它。这是很Pythonic的吗?如果不是,有没有人有一个我可以学习的Pythonic方法? - ciaran haines

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接