Pandas/matplotlib 条形图,颜色由列定义

4
我试图在Python中制作一个条形图,并根据数据帧列对条形进行着色,在R ggplot2中这非常容易,所以我真的不明白为什么在matplotlib/pandas中这么难,我希望了解如何做到这一点,也希望能够理解逻辑,因为我认为这并不难。
这是我想要的一个示例,在ggplot中完成的所有操作 - 我想要的只是使用数据框中的属性来定义颜色,该属性可以是颜色字符串,例如'k','r'等,也可以是数据的特征,比如男/女等。 enter image description here 下面是我尝试过的一些代码,用于生成条形图:
import matplotlib.pyplot as plt
import pandas as pd
data = pd.DataFrame({'name' : ['a','b','c'],'value' : [1,2,3], 
                     'c' : ['b','r','b']})
data.plot('name','value',kind='bar')

但是我希望颜色由列"c"定义

但是当我添加color='c'时,它不起作用

data.plot('name','value',color='c',kind='bar',color='c')

我尝试使用plot.scatter,但它也不起作用。

---- 更新

我做了更多的工作,这个方法或多或少有效,我还需要找出如何正确对齐标签,当轴是分类而不是数字时(ggplot2可以自行处理),我仍然不喜欢为什么必须有数字x轴 - 但至少这可以通过代码实现。

fig, ax = plt.subplots()
ax.bar(range(len(data)),data['value'],width=.5,color=data['c'])
ax.set_xticks(range(len(data)))
ax.set_xticklabels( (data['name'] ))

一如既往地感谢您


你能发布一个示例图吗?没有图片,很难知道你想要什么。 - Paul H
2个回答

2

试试这个:

data.plot('name','value',color=['r', 'g', 'b'],kind='bar')

您可以将任何颜色组合作为列表传递给color参数。如果有更多的条形图而颜色数量不够,颜色将循环使用。

enter image description here

我还强烈推荐优秀的brewer2mpl库。它提供了美观的颜色选择。 代码如下:

import brewer2mpl
bmap = brewer2mpl.get_map('Set2','qualitative',3,reverse=True)
colors = bmap.mpl_colors
data.plot('name','value',color=colors,kind='bar')

导致如下结果: enter image description here 您可以从这里获取brewer2mpl:https://pypi.python.org/pypi/brewer2mpl/1.4

1
感谢您的回答,也感谢您提供的建议。然而,这个解决方案并不适用于我,因为我不是在处理三个数据点(这只是一个例子),而是有很多更多的数据点,并且我正在使用代码在数据框中定义它们 - 真正的想法是让大多数条形图都是一种颜色,并且有一些(甚至只有一个)以不同的颜色显示。是否有一种方法可以根据数据来确定颜色?例如,在R中,所有需要传递给ggplot的就是fill = desired_column,它就会自动完成 - 我认为Python也应该有类似的功能。 - user1617979
谢谢您的评论!也感谢您对问题的更新! - user308827
有没有办法使用Brewer来选择您想要使用的特定颜色? - AGH_TORN
这个解决方案以前对我有用,但在我的当前pandas版本(0.20.3)中,它对所有条形图都使用了我color列表中的第一种颜色,并忽略了其他颜色。基于ax.bar()的op的解决方案仍然有效。 - patricksurry

0

模仿R行为并使用fill=desired_column的一种方法是创建一个新的“color”列,并在其中放置有效的颜色字符串,例如'r'、'g'、'b'或十六进制值等。这可以通过在所需列上使用map方法来完成。然后,您可以在绘图线中使用此颜色。

以下是OP案例的示例:

import matplotlib.pyplot as plt
import pandas as pd
data = pd.DataFrame({'name' : ['a','b','c'],'value' : [1,2,3], 
                     'c' : ['b','r','b']})

# Create new color column with map()
data['color'] = data['c'].map(lambda x: 'r' if x == 'b' else 'b')

# Plot with the new column 'color' as color argument
data.plot('name','value',kind='bar', color=data['color'])

如果在'c'中有更多不同的值而不仅仅是两个,那么一个更易读的版本可能是不使用一行if函数,而是按照以下步骤获取新的'color'列。

def let_to_color(let, col1, col2):
    if let == 'b':
        return col1
    elif let == 'r':
        return col2

data['color'] = data['c'].map(lambda x: let_to_color(x, '#ff5544', '#002211'))

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