使用matplotlib为不同的分类级别绘制不同的颜色


102

我有此数据帧diamonds,它由被等变量(carat, price, color),我想画的散点图pricecarat为每个color,这意味着不同的color具有在图中不同的颜色。

这很容易 Rggplot

ggplot(aes(x=carat, y=price, color=color),  #by setting color=color, ggplot automatically draw in different colors
       data=diamonds) + geom_point(stat='summary', fun.y=median)

在此处输入图片说明

我不知道如何在Python中使用matplotlib

PS:

我知道辅助绘图软件包,例如seabornggplot for python,我不喜欢它们,只是想了解是否有可能matplotlib单独使用; P 做这项工作。


1
在matplotlib中内置这样的东西真的很好,但是听起来并不容易。这里的讨论:github.com/matplotlib/matplotlib/issues/6214
naught101 '17

Answers:


156

您可以传递plt.scatter一个c参数,让您选择颜色。下面的代码定义了一个colors词典,用于将您的钻石颜色映射到绘图颜色。

import matplotlib.pyplot as plt
import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

fig, ax = plt.subplots()

colors = {'D':'red', 'E':'blue', 'F':'green', 'G':'black'}

ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))

plt.show()

df['color'].apply(lambda x: colors[x]) 有效地将颜色从“钻石”映射到“绘图”。

(原谅我没有放置另一个示例图像,我认为2就足够了:P)

seaborn

您可以使用seaborn其中的一个包装器matplotlib,使其在默认情况下看起来更漂亮(我基于观点,我知道:P),但是还添加了一些绘图功能。

为此,您可以使用seaborn.lmplotwith fit_reg=False(这样可以防止它自动进行某些回归)。

以下代码使用示例数据集。通过选择,hue='color'您可以告诉seaborn根据您的颜色拆分数据框,然后绘制每个数据框。

import matplotlib.pyplot as plt
import seaborn as sns

import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

sns.lmplot('carat', 'price', data=df, hue='color', fit_reg=False)

plt.show()

在此处输入图片说明

seaborn使用pandas.groupby

如果您不想使用seaborn,则可以使用它pandas.groupby来单独获得颜色,然后仅使用matplotlib绘制颜色,但是您必须随行手动分配颜色,下面添加了一个示例:

fig, ax = plt.subplots()

colors = {'D':'red', 'E':'blue', 'F':'green', 'G':'black'}

grouped = df.groupby('color')
for key, group in grouped:
    group.plot(ax=ax, kind='scatter', x='carat', y='price', label=key, color=colors[key])

plt.show()

此代码假定与上述相同的DataFrame,然后根据对其进行分组color。然后,对这些组进行迭代,为每个组进行绘制。为了选择一种颜色,我创建了一个colors字典,该字典可以将菱形颜色(例如D)映射为真实颜色(例如red)。

在此处输入图片说明


谢谢,但是我只想了解如何单独使用matplotlib来完成这项工作。
牛油果

是的,通过groupby我可以做到这一点,所以有一个功能matplotlib可以自动使用不同的颜色绘制不同类别​​的类别,对吗?
牛油果

@loganecolss好吧,我明白了:)我再次对其进行了编辑,并添加了一个非常简单的示例,该示例使用字典来映射颜色,类似于groupby示例。
Ffisegydd

1
@Ffisegydd使用第一种方法,ax.scatter您如何向其中添加图例?我试图用label=df['color'],然后plt.legend()没有成功。
ahoosh '16

1
这将是更好的改变ax.scatter(df['carat'], df['price'], c=df['color'].apply(lambda x: colors[x]))ax.scatter(df['carat'], df['price'], c=df['color'].map(colors)
张大伟

33

这是使用深蓝色调色板的简洁通用解决方案。

首先找到您喜欢的调色板,然后可视化它:

sns.palplot(sns.color_palette("Set2", 8))

然后,您可以通过以下方式使用它matplotlib

# Unique category labels: 'D', 'F', 'G', ...
color_labels = df['color'].unique()

# List of RGB triplets
rgb_values = sns.color_palette("Set2", 8)

# Map label to RGB
color_map = dict(zip(color_labels, rgb_values))

# Finally use the mapped values
plt.scatter(df['carat'], df['price'], c=df['color'].map(color_map))

2
我喜欢你的方法。给定上面的示例,您当然也可以将值映射到简单的颜色名称,如下所示:1)定义颜色color = {'D':'red','E':'blue','F':'green ','G':'black'} 2)像您一样映射它们:ax.scatter(df ['carat'],df ['price'],c = df ['color']。map(colors))
Stefan

1
但是,在这种情况下,如何按颜色添加标签?
弗朗索瓦·勒布朗

2
多补充一些抽象的,可以更换8sns.color_palette("Set2", 8)len(color_labels)
Swier

这很好,但是应该由seaborn自动完成。要每次快速绘制某些内容,必须每次都使用映射来分类变量,这令人难以置信。更不用说愚蠢的想法了,可以在情节上显示统计数据。不幸的是,由于这些原因,Seaborn作为一揽子计划正在下降
追逐

6

使用Altair

from altair import *
import pandas as pd

df = datasets.load_dataset('iris')
Chart(df).mark_point().encode(x='petalLength',y='sepalLength', color='species')

在此处输入图片说明


问题要求matplotlib
Chuck

6

我有同样的问题,并且整天都在尝试不同的软件包。

我最初使用的是matlibplot:并且对将类别映射到预定义的颜色都不满意。或分组/聚合,然后遍历各组(并且仍然必须映射颜色)。我只是觉得这是糟糕的软件包实施。

Seaborn无法处理我的案件,而Altair仅可在Jupyter Notebook内部使用。

对我而言,最好的解决方案是PlotNine,它“是基于ggplot2的Python图形语法的实现”。

以下是在Python中复制R示例的积木式代码:

from plotnine import *
from plotnine.data import diamonds

g = ggplot(diamonds, aes(x='carat', y='price', color='color')) + geom_point(stat='summary')
print(g)

紫水晶钻石示例

如此干净和简单:)


问题要求matplotlib
Chuck

5

这是定性颜色图中的标记和颜色的组合matplotlib

import itertools
import numpy as np
from matplotlib import markers
import matplotlib.pyplot as plt

m_styles = markers.MarkerStyle.markers
N = 60
colormap = plt.cm.Dark2.colors  # Qualitative colormap
for i, (marker, color) in zip(range(N), itertools.product(m_styles, colormap)):
    plt.scatter(*np.random.random(2), color=color, marker=marker, label=i)
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0., ncol=4);

在此处输入图片说明


mpl.cm.Dark2.colors- mpl似乎并没有在你的代码中定义,并Dark2没有属性colors
肖瓦尔特,

@Shovalt感谢您的审查。我应该将matplotlibas 导入mpl,通过使用plt其中也包含更正了我的代码cm。至少在matplotlib我使用的2.0.0版本中Dark2确实具有属性colors
Pablo Reyes

1
较晚,但如果您没有颜色属性:iter(plt.cm.Dark2(np.linspace(0,1,N)))
Geoff Lentsch

3

使用df.plot()

通常,在快速绘制DataFrame时,我使用pd.DataFrame.plot()。这将索引作为x值,将值作为y值,并分别用不同的颜色绘制每列。这种格式的DataFrame可以通过使用set_index和来实现unstack

import matplotlib.pyplot as plt
import pandas as pd

carat = [5, 10, 20, 30, 5, 10, 20, 30, 5, 10, 20, 30]
price = [100, 100, 200, 200, 300, 300, 400, 400, 500, 500, 600, 600]
color =['D', 'D', 'D', 'E', 'E', 'E', 'F', 'F', 'F', 'G', 'G', 'G',]

df = pd.DataFrame(dict(carat=carat, price=price, color=color))

df.set_index(['color', 'carat']).unstack('color')['price'].plot(style='o')
plt.ylabel('price')

情节

使用此方法,您不必手动指定颜色。

对于其他数据系列,此过程可能更有意义。就我而言,我有时间序列数据,因此MultiIndex包含日期时间和类别。也可以将这种方法用于多于一列的颜色,但是图例变得一团糟。


0

我通常使用基于Matplotlib构建的Seaborn来执行此操作

import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
              hue='species', data=iris); 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.