matplotlibを使用して、カテゴリレベルごとに異なる色をプロットする


101

diamondsような変数で構成されるこのデータフレームがあり、それぞれ(carat, price, color)に対してpricetoの散布図を描画したいのですが、これは、プロット内で異なる色が異なることを意味します。caratcolorcolor

これは容易である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:

seabornand などの補助プロットパッケージについて知っていますが、ggplot for pythonそれらを好みませんmatplotlib。単独で使用できるかどうかを確認したいだけです。; P


1
このようなものがmatplotlibに組み込まれていると非常に便利ですが、簡単ではないようです。ここでの議論:github.com/matplotlib/matplotlib/issues/6214
naught101

回答:


154

色を選択できるように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

seabornwhichは、matplotlibデフォルトできれいに見えるラッパーである(むしろ意見ベースで、私は:Pを知っています)を使用できますが、いくつかのプロット関数も追加します。

これについてはseaborn.lmplotfit_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だけで作業を行う方法を知りたいだけです。
アボカド2014年

はい、groupby私はそれを行うことができたのでmatplotlib、異なる色を使用してカテゴリカルの異なるレベルを自動的に描画できるような機能がありますよね?
アボカド2014年

@loganecolssわかりました:)もう一度編集して、groupby例のように、辞書を使用して色をマッピングする非常に単純な例を追加しました。
Ffisegydd 2014年

1
@Ffisegydd最初の方法であるを使用してax.scatter、どのように凡例を追加しますか?私が使用しようとしていますlabel=df['color']当時とplt.legend()成功しません。
2016

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)色を定義しますcolors = {'D': 'red'、 'E': 'blue'、 'F': 'green '、' G ':' black '} 2)マッピングしたとおりに:ax.scatter(df [' carat ']、df [' price ']、c = df [' color ']。map(colors))
ステファン

1
この場合、どのようにラベルを色で追加しますか?
フランソワ・ルブラン

2
いくつかのより多くの抽象化を追加するには、置き換えることができます8でのsns.color_palette("Set2", 8)ことでlen(color_labels)
Swier

これはすばらしいことですが、それは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でした。これは、「Pythonでのグラフィックの文法の実装であり、ggplot2に基づいています」。

以下は、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

@Shovaltレビューをありがとう。私はとしてインポートする必要がありましたmatplotlibmplpltも含むを使用してコードを修正しましたcm。少なくともmatplotlib私が2.0.0を使用しているバージョンにDark2は属性がありますcolors
Pablo Reyes

1
遅いが、colors属性がない場合: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')

プロット

この方法では、色を手動で指定する必要はありません。

この手順は、他のデータ系列に対してより意味がある場合があります。私の場合、timeseriesデータがあるので、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); 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.