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