如何为pandas/matplotlib条形图设置自定义颜色

116
我刚开始使用pandas/matplotlib来生成堆积条形图,以替代Excel。现在我遇到了以下问题:
(1) 默认的调色板只有五种颜色,所以如果我的类别超过了五个,那么颜色会重复。我该如何指定更多的颜色?最好是一个有起始颜色和结束颜色的渐变,并且能动态生成n个中间颜色。
(2) 颜色不是很美观。我该如何指定一组自定义的n个颜色?或者渐变也可以。
下面是一个示例,可说明上述两点:
  4 from matplotlib import pyplot
  5 from pandas import *
  6 import random
  7 
  8 x = [{i:random.randint(1,5)} for i in range(10)]
  9 df = DataFrame(x)
 10 
 11 df.plot(kind='bar', stacked=True)

输出结果如下图所示:

enter image description here

3个回答

158
您可以直接将plot函数的color选项指定为列表。
from matplotlib import pyplot as plt
from itertools import cycle, islice
import pandas, numpy as np  # I find np.random.randint to be better

# Make the data
x = [{i:np.random.randint(1,5)} for i in range(10)]
df = pandas.DataFrame(x)

# Make a list by cycling through the colors you care about
# to match the length of your data.
my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df)))

# Specify this list of colors as the `color` option to `plot`.
df.plot(kind='bar', stacked=True, color=my_colors)

要定义自己的自定义列表,你可以采取以下几种方法,或者只需查找Matplotlib技术来通过其RGB值定义颜色项目等。你可以根据需要进行复杂程度的定义。

my_colors = ['g', 'b']*5 # <-- this concatenates the list to itself 5 times.
my_colors = [(0.5,0.4,0.5), (0.75, 0.75, 0.25)]*5 # <-- make two custom RGBs and repeat/alternate them over all the bar elements.
my_colors = [(x/10.0, x/20.0, 0.75) for x in range(len(df))] # <-- Quick gradient example along the Red/Green dimensions.

最后一个示例为我产生了以下简单的颜色梯度:

enter image description here

我没有花太多时间来弄清楚如何强制图例选择定义的颜色,但我相信你可以做到。

总的来说,一个重要的建议是直接使用Matplotlib中的函数。从Pandas调用它们也可以,但我发现直接从Matplotlib调用它们可以获得更好的选项和性能。


3
小错误:在 Python 2.7 中,使用 my_colors = [cycle(['b', 'r', 'g', 'y', 'k']).next() for i in range(len(df))] 将始终给出 'b'。你应该使用 list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df))) 替代它。请注意不要改变原来的意思。 - vkontori
1
今天安装了pandas和matplotlib后,尽管代码可以运行,但是对我来说它没有生成任何内容。 - kakyo
@kakyo 你是在常规解释器、IPython还是从shell(或其他什么地方)运行?根据您在哪种类型的环境中执行此代码,您可能需要为matplotlib打开交互模式,或者为交互pylab设置pylab.ion() - ely
@endolith 是的,那些只是快速的例子。将列表连接到自身的部分与此问题或答案毫无关系。 - ely
1
上一个梯度命令产生了 ValueError(超出范围)ValueError: RGBA values should be within 0-1 range,需要针对其他数据进行调整。 - lys
显示剩余6条评论

60

我发现最简单的方法是在.plot()中使用colormap参数,其中包括预设的颜色渐变:

df.plot(kind='bar', stacked=True, colormap='Paired')

这里输入图像描述

您可以在此处找到大量预设的颜色地图列表

颜色地图


33
在我的情况下,这只会在所有条形图中产生一种颜色。 - tsando
我发现这些颜色地图列表很有用 https://matplotlib.org/examples/color/colormaps_reference.html https://gallantlab.github.io/colormaps.html - Al Po

21

如果您想获得更详细的关于创建自己的颜色映射的答案,我强烈建议访问此页面

如果这个答案太复杂了,您可以快速制作自己的颜色列表,并将它们传递给color参数。所有的颜色映射都在cm matplotlib模块中。 让我们从反向inferno颜色映射中获取30个RGB(加上 alpha)颜色值的列表。为此,请先获取颜色映射,然后将介于0和1之间的一系列值传递给它。 在这里,我们使用np.linspace 创建30个等间距值,在.4和.8之间表示颜色映射的这部分。

from matplotlib import cm
color = cm.inferno_r(np.linspace(.4, .8, 30))
color

array([[ 0.865006,  0.316822,  0.226055,  1.      ],
       [ 0.851384,  0.30226 ,  0.239636,  1.      ],
       [ 0.832299,  0.283913,  0.257383,  1.      ],
       [ 0.817341,  0.270954,  0.27039 ,  1.      ],
       [ 0.796607,  0.254728,  0.287264,  1.      ],
       [ 0.775059,  0.239667,  0.303526,  1.      ],
       [ 0.758422,  0.229097,  0.315266,  1.      ],
       [ 0.735683,  0.215906,  0.330245,  1.      ],
       .....

然后我们可以使用这个来绘图,使用原始帖子中的数据:

import random
x = [{i: random.randint(1, 5)} for i in range(30)]
df = pd.DataFrame(x)
df.plot(kind='bar', stacked=True, color=color, legend=False, figsize=(12, 4))

输入图像描述


2
这里是除了 inferno_r 之外的其他颜色地图的文档:https://matplotlib.org/examples/color/colormaps_reference.html - tsando
3
我遵循了这段代码,但我的颜色数组始终具有相同的值。 - FaCoffee

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