φυβλαςのβλογ
บล็อกของ phyblas



numpy & matplotlib เบื้องต้น บทที่ ๓๖: การเพิ่มเส้นและรูปร่างต่างๆ
เขียนเมื่อ 2016/06/25 23:32
แก้ไขล่าสุด 2022/07/21 20:40
นอกจากแกนกราฟและเส้นกราฟแล้ว บางทีเราอาจยังต้องการวาดส่วนประกอบอะไรเล็กๆน้อยๆเสริมลงไปอีก matplotlib มีคำสั่งสำหรับใส่อะไรต่างๆอยู่มากมาย



การขีดเส้นตรงแนวตั้งและนอน
เส้นตรงแนวตั้งวาดโดย plt.axvline และเส้นตรงแนวนอนวาดโดย plt.axhline

อาร์กิวเมนต์ที่ต้องใส่คือตำแหน่งพิกัดบนแกนกราฟที่จะวาดกราฟ

แต่ถ้าใส่อาร์กิวเมนต์ตัวที่ ๒ จะเป็นการกำหนดขอบเขตล่าง และตัวที่ ๓ เป็นการกำหนดขอบเขตบน โดยหน่วยในที่นี้จะไม่ใช่ค่าบนแกนกราฟแต่เป็นตำแหน่งบนฉาก สำหรับแนวตั้งนับจากล่างสุดเป็น 0 บนสุดเป็น 1 แนวนอนไล่จากซ้ายสุดเป็น 0 ขวาสุดเป็น 1

เส้นที่ได้ออกมานี้จริงๆแล้วถือเป็นออบเจ็กต์ชนิดเดียว กับเส้นกราฟ คือเป็นออบเจ็กต์ชนิด matplotlib.lines.Line2D ซึ่งเป็นออบเจ็กต์ของเส้นที่ลากเชื่อมจุดต่อจุด

สามารถใส่คีย์เวิร์ด เพื่อคุณสมบัติเพิ่มเติมลงไปได้ในลักษณะเช่นเดียวกับเวลาที่วาดกราฟด้วย ฟังก์ชัน plot เช่น color, linestyle, linewidth, marker, alpha, ฯลฯ รายละเอียดดูได้ที่ตารางตอนท้ายบทที่ ๕

ตัวอย่าง
import numpy as np
import
matplotlib.pyplot as plt
ax = plt.axes(xlim=[-100,100],ylim=[-75,75],aspect=1)
plt.axvline(15)
plt.axhline(35,c='m',lw=3)
plt.axvline(25,0.2,0.8,c='g',lw=8)
plt.axhline(50,0.1,0.5,c='c',lw=5,ls='--',marker='D',mfc='b',ms=10,mew=3,mec='r')
plt.show()



จะเห็นว่าดูแล้วก็ไม่ต่างจากการวาดกราฟ โดยเป็นกราฟที่วาดขึ้นจากจุดสองจุด เพียงแต่ว่าจุดต้นกับปลายนั้นถูกกำหนดด้วยค่าตำแหน่งที่เทียบกับกรอบ (ค่า 0 ถึง 1) แทนที่จะเป็นค่าบนแกนกราฟ



การวาดแถบสี่เหลี่ยม
เช่นเดียวกับการแทรกเส้น การแทรกแถบสี่เหลี่ยมลงบนกราฟก็ทำได้ด้วยวิธีการที่คล้ายกัน แถบแนวตั้งใช้ plt.axvspan ส่วนแถบแนวนอนใช้ plt.axhspan

สำหรับ plt.axvspan จะกำหนดขอบเขตซ้ายและขวาก่อนด้วยอาร์กิวเมนต์สองตัวแรก ส่วนขอบเขตล่างกับบนจะใส่ในตำแหน่งที่ ๓ และ ๔ โดยจะใส่หรือไม่ก็ได้
plt.axvspan(ขอบเขตซ้าย, ขอบเขตขวา, ขอบเขตล่าง, ขอบเขตบน)

ให้ระวังว่าหน่วยที่ใช้นั้นจะต่างกัน โดยขอบเขตซ้ายขวาหน่วยเป็นค่าตามในข้อมูล ส่วนขอบเขตบนล่างหน่วยเป็นตำแหน่งเทียบกับกรอบ (ค่า 0 ถึง 1)

ตัวอย่าง
x = np.linspace(0,200,1001)
y = -np.cos(x/10)*2+np.sin((x-100)**2)*np.exp(-(x-100)**2/100)
plt.axvspan(80,120,alpha=0.2,lw=7,fc='r',ec='k')
plt.plot(x,y)
plt.show()



ถ้าต้องการจำกัดให้ทับแค่บางส่วนก็แก้เป็น
plt.axvspan(80,120,0.34,0.99,alpha=0.2,lw=7,fc='r',ec='k')



กรณีที่ใช้ plt.axhspan นั้นจะตรงกันข้ามกัน โดยกำหนดขอบเขตล่างและบนก่อนด้วยอาร์กิวเมนต์สองตัวแรก แล้วจึงตามด้วยขอบเขตซ้ายขวา
plt.axhspan(ขอบเขตล่าง, ขอบเขตบน, ขอบเขตซ้าย, ขอบเขตขวา)

ตัวอย่าง
x = np.linspace(80,120,1001)
y = np.sin(x/40*np.pi)*10+np.sin((x-100)**2)*np.exp(-(x-100)**2/20)
plt.axhspan(7,y.max(),alpha=0.2,lw=7,fc='g',ec='k')
plt.plot(x,y,'c')
plt.show()



แถบสี่เหลี่ยมที่ได้ออกมาจาก plt.axvspan และ plt.axhspan นั้นเป็นออบเจ็กต์ชนิด matplotlib.patches.Polygon ซึ่งเป็นออบเจ็กต์ของรูปหลายเหลี่ยม

ปกติเวลาใช้ plt.axvspan หรือ plt.axhspan จะเป็นการสร้างออบเจ็กต์ชนิดนี้ขึ้นมาแล้วใส่ลงบน axes โดยอัตโนมัติ

แต่ออบเจ็กต์ชนิดนี้สามารถทำเป็นรูปร่างได้หลากหลายไม่เพียงแค่สี่เหลี่ยม เท่านั้น หากต้องการวาดรูปหลายเหลี่ยมเราอาจทำการสร้าง matplotlib.patches.Polygon ขึ้นมาแล้วจึงนำมาแทรกลงบน axes



การวาดรูปหลายเหลี่ยม
matplotlib.patches.Polygon นั้นอยู่ในมอดูลย่อยของ matplotlib ที่ชื่อ patches แต่ว่าก็มีอยู่ใน plt (matplotlib.pyplot) ด้วย ดังนั้นเวลาจะสร้างสามารถพิมพ์เป็น plt.Polygon แทนที่จะพิมพ์ mpl.patches.Polygon (ในที่นี้ import matplotlib as mpl)

อาร์กิวเมนต์ ที่ต้องใช้สำหรับฟังก์ชันนี้คือลิสต์ของตำแหน่งมุมทั้งหมดโดยเรียงตามลำดับ กล่าวคือ [[x1,y1],[x2,y2],...,[xN,yN]] หรืออาจอยู่ในรูปของอาเรย์สองมิติที่มีขนาดเป็น Nx2 โดย N เป็นจำนวนจุดมุม

ต่อจากอาร์กิวเมนต์ก็เป็นคีย์เวิร์ดต่างๆสำหรับกำหนดคุณสมบัติของรูปที่จะวาด

คีย์เวิร์ดสำหรับตั้งค่าที่สามารถใช้ได้ใน Polygon
คีย์เวิร์ด ชื่อย่อ ความหมาย
alpha   ความโปร่งใส
color   สีของทั้งเส้นขอบและพื้นผิว
edgecolor ec สีเส้นขอบ
facecolor fc สีพื้นผิว
fill   กำหนดว่าจะระบายสีหรือไม่ 0 ไม่ 1 ระบาย ค่าตั้งต้นคือ 1
hatch   ลวดลาย
linestyle ls รูปแบบของเส้นขอบ
linewidth lw ความหนาของเส้นขอบ
zorder   ลำดับความสำคัญ (ยิ่งค่ามากยิ่งทับอยู่ด้านบน)

และสุดท้าย ออบเจ็กต์ที่สร้างขึ้นมาจะยังไม่ปรากฏบนฉาก แต่จะต้องนำมาใส่ลงไปอีกที โดยใช้เมธอด add_patch ที่ตัว axes ทีจะวาด

ตัวอย่าง
mum = np.array([[0,0],[1,1],[2,0],[1,-3]])
p = plt.Polygon(mum,fc='#aaffaa',lw=3,ls='-.',ec='#aa2222',hatch='*')
plt.figure(figsize=[6,8])
ax = plt.axes(xlim=[-0.5,2.5],ylim=[-3.5,1.5],aspect=1)
ax.add_patch(p)
plt.show()



เราอาจกำหนดพิกัดแกน x และ y ของแต่ละจุดด้วยวิธีที่คล้ายกับตอนวาดกราฟ จากนั้นก็ใช้ฟังก์ชัน np.stack โดยใส่คีย์เวิร์ด axis=1 แบบนี้ก็สามารถใช้ใน plt.Polygon ได้แล้ว

ตัวอย่าง
theta = np.linspace(0,360,41)
r = 3+np.sin(np.radians(theta*10))
x = r*np.cos(np.radians(theta))
y = r*np.sin(np.radians(theta))
p = plt.Polygon(np.stack((x,y),axis=1),fc='#ffaaaa',lw=25,ec='#ff3333',hatch='oOx')
plt.figure(figsize=[7,7])
ax = plt.axes(xlim=[-5,5],ylim=[-5,5],aspect=1,facecolor='#ccffcc')
ax.add_patch(p)
plt.show()





นอกจากนี้ยังมีออบเจ็กต์ชนิด matplotlib.patches.Rectangle ซึ่งใช้วาดรูปสี่เหลี่ยมโดยเฉพาะ กรณีที่ต้องการสร้างสี่เหลี่ยมหากใช้อันนี้จะสร้างได้ง่ายกว่า

ออบเจ็กต์นี้ความจริงแล้วเป็นตัวเดียวกับที่ได้จากแผนภูมิแท่ง (ดูบทที่ ๑๒) เวลาสั่งวาดแผนภูมิแท่งนั้นก็คือการสร้างออบเจ็กต์ชนิดนี้ขึ้นมาหลายๆอันโดยอัตโนมัตินั่นเอง

Rectangle สามารถเรียกใช้จากใน plt ได้เช่นเดียวกับ Polygon คือใช้เป็น plt.Rectangle แทน mpl.patches.Rectangle ได้

รูปแบบการใช้คือ
plt.Rectangle(ตำแหน่ง, ความกว้าง, ความสูง, angle=มุมเอียง, คีย์เวิร์ดอื่นๆเพิ่มเติม)

ตัวอย่าง สร้างสี่เหลี่ยมผืนผ้าที่สุ่มทั้งตำแหน่ง, ขนาด, มุมเอียง, และสี วางกระจายอยู่ทั่วฉาก
ax = plt.axes([0.05,0.05,0.9,0.9],xlim=[-36,36],ylim=[-26,26],aspect=1)
for i in range(1000):
    x = np.random.uniform(-40,40)
    y = np.random.uniform(-30,30)
    kx = np.random.uniform(2,20)
    ky = np.random.uniform(2,20)
    mum = np.random.uniform(0,180)
    fc = plt.get_cmap('rainbow')(np.random.rand())
    p = plt.Rectangle([x,y],kx,ky,angle=mum,fc=fc,alpha=0.2,lw=0)
    ax.add_patch(p)
plt.show()





การวาดวงรีและวงกลม
ออบเจ็กต์สำหรับวงรีคือ matplotlib.patches.Ellipse

Ellipse นี้ต่างจาก Polygon และ Rectangle ตรงที่ไม่มีอยู่ใน plt ดังนั้นต้องพิมพ์ mpl.patches.Ellipse เท่านั้น ไม่สามารถใช้เป็น plt.Ellipse

รูปแบบการใช้
mpl.patches.Ellipse(ตำแหน่ง, ความกว้าง, ความสูง, angle=มุมเอียง, คีย์เวิร์ดอื่นๆเพิ่มเติม)

ตัวอย่าง
import matplotlib as mpl
ax = plt.axes(xlim=[-4,6],ylim=[-4,4],aspect=1)
p = mpl.patches.Ellipse([1,0],8,5,angle=30,fc='m',ec='k')
ax.add_patch(p)
p = mpl.patches.Ellipse([1,0],7,4,angle=-30,fc='r',alpha=0.5,lw=5,ec='k')
ax.add_patch(p)
plt.show()



สำหรับวงกลมอาจใช้ออบเจ็กต์ชนิด matplotlib.patches.Circle ซึ่งก็ถือเป็นซับคลาสของ matplotlib.patches.Ellipse อีกที

รูปแบบการใช้
mpl.patches.Circle(ตำแหน่ง, radius=รัศมี, คีย์เวิร์ดอื่นๆเพิ่มเติม)



การวาดส่วนตัดวงกลม
หากต้องการวาดภาพส่วนตัดบางส่วนของวงกลมสามารถใช้ออบเจ็กต์ mpl.patches.Wedge

รูปแบบการใช้
mpl.patches.Wedge(ตำแหน่งใจกลาง, r=รัศมี, theta1=มุมเริ่มกวาด, theta2=มุมหยุดกวาด, width=ความกว้าง, คีย์เวิร์ดอื่นๆเพิ่มเติม)

ตัวอย่าง
ax = plt.axes(xlim=[-5,5],ylim=[-3,5],aspect=1)
p = mpl.patches.Wedge([0,0],r=5,theta1=-30,theta2=180,width=2,lw=3,ec='r',fc='c')
ax.add_patch(p)
plt.show()



ค่า width ถ้าไม่ได้กำหนดก็จะได้เป็นเหมือนชิ้นพิซซาหรือแพ็กแมน

ตัวอย่าง
ax = plt.axes(xlim=[-5,7],ylim=[-5,5],aspect=1)
p = mpl.patches.Wedge([2,0],r=4,theta1=-22.5,theta2=22.5,fc='#ffc789',ec='#8d4c23')
ax.add_patch(p)
p = mpl.patches.Wedge([2,0],r=4,theta1=-22.5,theta2=22.5,width=0.8,fc='#c69144',ec='#8d4c23')
ax.add_patch(p)
p = mpl.patches.Wedge([0,0],r=4,theta1=22.5,theta2=-22.5,fc='#ffc789',ec='#8d4c23')
ax.add_patch(p)
p = mpl.patches.Wedge([0,0],r=4,theta1=22.5,theta2=-22.5,width=0.8,fc='#c69144',ec='#8d4c23')
ax.add_patch(p)
p = mpl.patches.Circle([-1,1],radius=0.5,fc='#aa2f1b',lw=5,ec='k')
ax.add_patch(p)
plt.show()





การวาดส่วนของเส้นโค้ง
ออบเจ็กต์ของส่วนของเส้นโค้งคือ matplotlib.patches.Arc ซึ่งก็เป็นซับคลาสอันหนึ่งของ matplotlib.patches.Ellipse การสร้างคล้ายกับวงรี เพียงแต่เพิ่มคีย์เวิร์ดที่กำหนดว่าจะวาดส่วนโค้งที่มีมุมเริ่มกวาดและหยุด กวาดเมื่อไหร่

รูปแบบ
mpl.patches.Arc(ตำแหน่งxy, ความกว้าง, ความสูง, angle=มุมเอียง, theta1=มุมเริ่มกวาด, theta2=มุมหยุดกวาด, คีย์เวิร์ดอื่นๆเพิ่มเติม)

ตัวอย่าง ลองใช้รูปวงรีและส่วนของเส้นโค้งมาวาดเป็นหน้าคิวเบย์ 
ax = plt.axes(xlim=[-15,15],ylim=[-8,12],aspect=1)
plt.text(0,11,u'มาทำสัญญากับผม\nแล้วเป็นสาวน้อยเวทมนตร์เถอะ!',fontname='Tahoma',fontsize=18,ha='center',va='top')
p = []
# ใบหน้า
p += [mpl.patches.Ellipse([0,0],18,15,fc='w',ec='k')]
# ตาขวา
p += [mpl.patches.Ellipse([-5,1],2.4,2.4,fc='#d86089',ec='k')]
p += [mpl.patches.Ellipse([-5,1],1.2,1.2,fc='#6f2624',lw=0)]
p += [mpl.patches.Ellipse([-4.5,1.5],0.7,0.7,fc='w',lw=0)]
# ตาซ้าย
p += [mpl.patches.Ellipse([5,1],2.4,2.4,fc='#d86089',ec='k')]
p += [mpl.patches.Ellipse([5,1],1.2,1.2,fc='#6f2624',lw=0)]
p += [mpl.patches.Ellipse([5.5,1.5],0.7,0.7,fc='w',lw=0)]
# ปาก
p += [mpl.patches.Arc([-1.2,-4],2.4,1.2,theta1=180,theta2=360)]
p += [mpl.patches.Arc([1.2,-4],2.4,1.2,theta1=180,theta2=360)]
for x in p:
    ax.add_patch(x)
plt.show()



ข้อความมาจาก http://hinaboshi.com/walidet/588511551167620



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



อ้างอิง

<< บทที่แล้ว     บทถัดไป >>
หน้าสารบัญ


-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> matplotlib

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

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文