φυβλαςのβλογ
บล็อกของ 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)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文