พล็อตสีที่แตกต่างกันสำหรับระดับหมวดหมู่ต่างๆโดยใช้ matplotlib


104

ฉันมีกรอบข้อมูลนี้diamondsซึ่งประกอบด้วยตัวแปรเหมือน(carat, price, color)และผมต้องการที่จะดึงพล็อตกระจายpriceไปcaratสำหรับแต่ละcolorซึ่งหมายถึงการที่แตกต่างกันcolorจะมีสีที่แตกต่างกันในการวางแผน

ทำได้ง่ายRด้วยggplot:

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:

ฉันรู้เกี่ยวกับแพคเกจการวางแผนเสริมเช่นseabornและggplot for pythonและฉัน Donot ชอบพวกเขาเพียงแค่ต้องการที่จะหาถ้ามันเป็นไปได้ที่จะทำผลงานได้โดยใช้matplotlibเพียงอย่างเดียว; P


1
มันจะดีมากที่มีบางอย่างเช่นนี้ใน matplotlib แต่ดูเหมือนว่ามันจะไม่ง่าย พูดคุยกันที่นี่: github.com/matplotlib/matplotlib/issues/6214
naught101

คำตอบ:


159

คุณสามารถส่งผ่านอาร์กิวเมนต์ซึ่งจะช่วยให้คุณสามารถเลือกสี โค้ดด้านล่างนี้กำหนดพจนานุกรมเพื่อจับคู่สีเพชรของคุณกับสีที่ลงจุดplt.scatterccolors

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.lmplotกับfit_reg=False(ซึ่งป้องกันไม่ให้ทำการถดถอยโดยอัตโนมัติ)

โค้ดด้านล่างใช้ชุดข้อมูลตัวอย่าง โดยการเลือกhue='color'คุณบอกให้ซีบอร์นแบ่งดาต้าเฟรมของคุณตามสีของคุณจากนั้นจึงลงจุดแต่ละอัน

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

หากคุณไม่ต้องการใช้นกทะเลคุณสามารถใช้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

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)
ทวาย

38

นี่เป็นวิธีแก้ปัญหาแบบรวบรัดและทั่วไปในการใช้จานสีของทะเล

ก่อนอื่นให้ค้นหาจานสีที่คุณชอบและเลือกให้เห็นภาพ:

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))
Stefan

1
คุณจะเพิ่มฉลากตามสีอย่างไรในกรณีนี้
François Leblanc

3
เพื่อเพิ่มบางสิ่งที่เป็นนามธรรมมากขึ้นคุณสามารถแทนที่8ในโดยsns.color_palette("Set2", 8) len(color_labels)
Swier

นี่เป็นสิ่งที่ดี แต่ควรทำโดยอัตโนมัติโดยใช้ทะเล การต้องใช้แผนที่สำหรับตัวแปรจัดหมวดหมู่ทุกครั้งที่คุณต้องการพล็อตบางสิ่งอย่างรวดเร็วนั้นเป็นอุปสรรคอย่างมาก ไม่ต้องพูดถึงความคิดงี่เง่าที่จะดึงเอาความสามารถในการแสดงสถิติของพล็อตออกมา น่าเสียดายที่ Seaborn ลดลงในรูปแบบแพ็คเกจเนื่องจากเหตุผลเหล่านี้
ไล่ล่า

7

ฉันมีคำถามเดียวกันและใช้เวลาทั้งวันในการลองใช้แพ็คเกจต่างๆ

เดิมทีฉันใช้ matlibplot: และไม่พอใจกับการแมปประเภทใดประเภทหนึ่งกับสีที่กำหนดไว้ล่วงหน้า หรือจัดกลุ่ม / รวมแล้ววนซ้ำผ่านกลุ่มต่างๆ (และยังต้องแมปสี) ฉันรู้สึกว่ามันใช้งานแพ็คเกจได้ไม่ดี

Seaborn ไม่สามารถใช้งานได้ในกรณีของฉันและ Altair ใช้งานได้ภายใน Jupyter Notebook เท่านั้น

ทางออกที่ดีที่สุดสำหรับฉันคือ PlotNine ซึ่ง "เป็นการใช้ไวยากรณ์ของกราฟิกใน Python และใช้ ggplot2"

ด้านล่างนี้คือรหัส plotnine เพื่อจำลองตัวอย่าง R ของคุณใน Python:

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

นี่คือการรวมกันของเครื่องหมายและสีจาก colormap เชิงคุณภาพใน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 ขอบคุณสำหรับรีวิว ฉันควรนำเข้าmatplotlibเนื่องจากmplฉันได้แก้ไขรหัสของฉันโดยใช้pltซึ่งมี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_indexunstack

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

ฉันมักจะใช้ Seaborn ซึ่งสร้างขึ้นจาก matplotlib

import seaborn as sns
iris = sns.load_dataset('iris')
sns.scatterplot(x='sepal_length', y='sepal_width',
              hue='species', data=iris); 

0

คุณสามารถแปลงคอลัมน์หมวดหมู่ให้เป็นคอลัมน์ตัวเลขได้โดยใช้คำสั่ง:

#we converting it into categorical data
cat_col = df['column_name'].astype('categorical') 

#we are getting codes for it 
cat_col = cat_col.cat.codes 

# we are using c parameter to change the color.
plt.scatter(df['column1'],df['column2'], c=cat_col) 

โปรดทราบว่าคุณอาจจะต้องไม่astype('category') categorical
j6m8
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.