หลังจากที่
บทที่แล้วได้เรียนรู้ส่วนประกอบของฉากที่ใช้กราฟไปแล้ว คราวนี้จะมาลองดูวิธีการปรับแต่งต่างๆ
การปรับขนาดของภาพ ในตัวอย่างในบทที่ผ่านๆมาเราวาดกราฟโดยที่ไม่ได้กำหนดขนาด ซึ่งจะเห็นว่ากราฟที่ได้ออกมามีขนาดเป็นค่ามาตรฐานค่าหนึ่ง
เช่นลอง
import numpy as np
import matplotlib.pyplot as plt
theta = np.radians(np.linspace(0,360,73))
x = 10*np.cos(theta)
y = 10*np.sin(theta)
plt.plot(x,y)
plt.show()
สมการที่ใช้เป็นของกราฟวงกลม แต่เพราะแกนตั้งและนอนไม่เท่ากันเลยทำให้ภาพดูออกมาเหมือนเป็นวงรี ดังนั้นเราควรจะปรับภาพให้มีความกว้างและสูงเท่าๆกัน
เราสามารถปรับขนาดของภาพได้ด้วยการเติมคีย์เวิร์ดในฟังก์ชัน plt.figure
คีย์เวิร์ดที่เกี่ยวข้องมีอยู่ ๒ ตัวคือ figsize และ dpi
figsize คือขนาดของรูปในแนวตั้งและแนวนอน โดยต้องใส่ในรูปทูเพิลหรือลิสต์ มีหน่วยเป็นนิ้ว 1 นิ้วคือ 80 พิกเซลเป็นมาตรฐาน
ค่า figsize มาตรฐานจะเป็น 8x6 ดังนั้นจึงได้ภาพขนาด 640x480 อย่างไรก็ตามอาจมีความต่างไปตามคอมไพเลอร์ที่ใช้
จำนวนพิกเซลต่อนิ้วก็สามารถปรับได้ด้วยการใส่คีย์เวิร์ด dpi ยิ่งค่ามากภาพก็จะยิ่งใหญ่ ขนาดของภาพที่ได้ก็คือ figsize คูณด้วย dpi
ลองแก้ส่วนวาดกราฟเป็น
plt.figure(figsize=[5,5],dpi=40)
plt.plot(x,y)
plt.show()
แบบนี้จะได้ภาพขนาด 200x200 พิกเซล
ตอนที่เซฟภาพด้วยฟังก์ชัน savefig จะต้องปรับค่า dpi อีกทีด้วยการใส่คีย์เวิร์ด ค่า dpi ที่ปรับที่ figsize จะไม่มีผล ดังนั้นหากต้องการเซฟภาพขนาดเท่าเดิมก็พิมพ์
plt.savefig('wongklom.png',dpi=40)
การแต่งสีและขอบของภาพ นอกจากปรับขนาดแล้วก็ยังสามารถปรับสีและขอบของภาพได้ด้วย คีย์เวิร์ดที่เกี่ยวข้องมีดังนี้
facecolor |
สีพื้นหลัง |
edgecolor |
สีขอบ |
linewidth |
ความกว้างขอบ |
figsize |
ขนาดภาพในหน่วยนิ้ว [แนวตั้ง,แนวนอน] |
dpi |
สัดส่วนพิกเซลต่อนิ้ว |
ลอง
theta = np.radians(np.linspace(0,360,73))
x = 10*np.cos(theta)
y = 10*np.sin(theta)
plt.figure(figsize=[5,5],dpi=60,edgecolor='#AA1111',linewidth=15,facecolor='#99DDFF')
plt.plot(x,y)
plt.show()
ได้กราฟออกมาแลดูสวยงาม
คีย์เวิร์ดต่างๆที่ปรับลงไปเหล่านี้เวลาที่เซฟภาพก็ต้องใส่ลงในฟังก์ชัน savefig เช่นกัน ไม่เช่นนั้นภาพที่ได้ก็จะยังคงเป็นสีขาวโล่ง
การปรับขอบเขตของกราฟ ปกติถ้าเราไม่ได้ตั้งว่าขอบเขตของกราฟเป็นเท่าใดโปรแกรมจะทำการหาตามความเหมาะสมให้เอง แต่บางครั้งก็อาจไม่ได้ถูกใจเสมอไป ดังนั้นจึงอาจต้องกำหนดเขตใหม่เพื่อให้ได้ตามแบบที่ต้องการ
การปรับขอบเขตสามารถทำได้ด้วยฟังก์ชัน plt.axes
คีย์เวิร์ดที่ต้องใส่คือ xlim และ ylim โดยค่าที่ต้องใส่คือทูเพิลหรือลิสต์ขอบเขต xlim=[ซ้าย, ขวา], ylim=[ล่าง, บน]
ตัวอย่าง
theta = np.radians(np.linspace(0,10000,2001))
x = 10*np.cos(theta)/(100+theta)
y = 10*np.sin(theta)/(100+theta)
plt.figure(edgecolor='#AA1111',linewidth=10,facecolor='#AAFFEE')
plt.axes(xlim=[-0.16,0.16],ylim=[-0.12,0.12])
plt.plot(x,y,c='#EE2211')
plt.show()
การปรับตำแหน่งและตัวเลขขีดพิกัด นอกจากจะปรับขอบเขตแล้วเรายังสามารถปรับเส้นขีดที่บอกตำแหน่งได้ด้วย จากที่ปกติจะถูกกำหนดโดยอัตโนมัติตามความเหมาะสม สามารถทำได้โดยเพิ่มคีย์เวิร์ด xticks และ yticks ค่าที่ต้องใส่คือลิสต์หรืออาเรย์ไล่เรียงตำแหน่งขีด
np.linspace น่าจะเป็นฟังก์ชันที่เหมาะในการสร้างอาเรย์เพื่อใช้ในการนี้ เพราะสามารถกำหนดขอบเขตและขีดให้เว้นระยะเท่าๆตามจำนวนที่ต้องการได้
ลองดูกราฟเดิม
theta = np.radians(np.linspace(0,10000,2001))
x = 10*np.cos(theta)/(100+theta)
y = 10*np.sin(theta)/(100+theta)
plt.figure(edgecolor='#1111AA',linewidth=10,facecolor='#AAFFEE')
plt.axes(xlim=[-0.16,0.16],ylim=[-0.12,0.12],
xticks=np.linspace(-0.16,0.16,9),
yticks=np.linspace(-0.11,0.11,12))
plt.plot(x,y,c='#EE2211')
plt.show()
จะเห็นว่าจำนวนขีดเพิ่มขึ้นตามที่ต้องการ
นอกจากนี้ยังสามารถแก้ไขตัวหนังสือที่ขีดบอก โดยเพิ่มคีย์เวิร์ด yticklabels และ xticklabels โดยใส่ค่าเป็นรายการของสายอักขระ
สิ่งที่ใส่จะเป็นอะไรก็ได้ ในที่นี้จะลองใส่เป็นตัวเลขแล้วบวกด้วยหน่วย ซึ่งก็สามารถทำได้ง่าย
แก้กราฟเป็นตามนี้ โดยเพิ่ม yticklabels และ xticklabels เข้าไป
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
xlim = [-0.16,0.16]
ylim = [-0.12,0.12]
xticks = np.linspace(-0.16,0.16,9)
yticks = np.linspace(-0.11,0.11,12)
xticklabels = ['%.2fcm'%s for s in xticks]
yticklabels = ['%.2fcm'%s for s in yticks]
plt.axes(xlim=xlim,ylim=ylim,xticks=xticks,yticks=yticks,yticklabels=yticklabels,xticklabels=xticklabels)
plt.plot(x,y,c='#EE2211')
plt.show()
จะได้ว่ามีคำว่า cm เพิ่มเข้ามาในกราฟ
อนึ่ง ขนาดและรูปแบบของตัวหนังสือเองก็เป็นอะไรที่สามารถปรับได้ด้วย แต่จะขอยังไม่พูดถึงในบทนี้ ยกไปพูดถึงใน
บทหน้า นอกจากนี้แล้วการตั้งค่าต่างๆนี้อาจทำได้โดยใช้เมธอดที่ออบเจ็กต์ axes ซึ่งอาจใช้ฟังก์ชัน gca เพื่อนำเอาออบเจ็กต์ตัว axes นั้นมาจัดการ
เมธอดเหล่านี้ล้วนขึ้นต้นด้วยคำว่า set_ เช่น set_xlim, set_ylim, set_xticks, set_yticks เป็นต้น
ตัวอย่างข้างต้นอาจเขียนใหม่ด้วยวิธีนี้ได้เป็น
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
ax = plt.gca()
ax.set_xlim([-0.16,0.16])
ax.set_ylim([-0.12,0.12])
ax.set_xticks(np.linspace(-0.16,0.16,9))
ax.set_yticks(np.linspace(-0.11,0.11,12))
ax.set_xticklabels(['%.2fcm'%s for s in np.linspace(-0.16,0.16,9)])
ax.set_yticklabels(['%.2fcm'%s for s in np.linspace(-0.11,0.11,12)])
plt.plot(x,y,c='#EE2211')
plt.show()
ผลที่ได้จะเหมือนกับตัวอย่างที่แล้วแต่จะเขียนยาวกว่าหน่อยเพราะต้องมีการเอาตัวแปร ax มารับด้วยเพื่อจะนำมาเรียกใช้เพื่อการปรับค่าในบรรทัดต่อๆมา
หรือนอกจากนี้แล้วก็อาจเขียนสั้นง่ายกว่านั้นโดยโดยใช้ฟังก์ชัน plt.xlim, plt.ylim, plt.xticks และ plt.yticks โดยไม่จำเป็นต้องไปดึงเอาออบเจ็กต์ตัว axes มาเลยก็ได้ เช่น
plt.figure(edgecolor='#11AA11',linewidth=10,facecolor='#FFAAEE')
plt.xlim([-0.16,0.16])
plt.ylim([-0.12,0.12])
plt.xticks(np.linspace(-0.16,0.16,9),['%.2fcm'%s for s in np.linspace(-0.16,0.16,9)])
plt.yticks(np.linspace(-0.11,0.11,12),['%.2fcm'%s for s in np.linspace(-0.11,0.11,12)])
plt.plot(x,y,c='#EE2211')
plt.show()
เพียงแต่มีข้อแตกต่างคือจะสังเกตได้ว่าในที่นี้ plt.xticks จะใช้แทนทั้ง set_xticks และ set_xticklabels ไปในเวลาเดียวกันเลย แต่ไม่มีฟังก์ชัน plt.xticklabels ดังนั้นต้องระวังอย่าสับสนตรงนี้ด้วย
นอกจากนั้นแล้ว ในทางตรงข้ามกับ set_ เรายังสามารถดูค่าต่างๆของ axes นั้นได้ด้วยเมธอดที่ขึ้นต้นด้วย get_
print(ax.get_xlim()) # ได้ (-0.16, 0.16)
print(ax.get_xticks()) # ได้ [-0.16 -0.12 -0.08 -0.04 0. 0.04 0.08 0.12 0.16]
นอกจากนี้ยังมีวิธีอื่นการปรับตำแหน่งและรูปแบบการแสดงผลของเลขขีดบนกราฟซึ่งอาจจะเข้าใจยากกว่าแต่ค่อนข้างสะดวกกว่า ซึ่งจะพูดถึงใน
บทที่ ๓๗ การควบคุมสัดส่วนของ x และ y ในกราฟ จะเห็นว่าพอปรับ xlim และ ylim ก็จะทำให้สัดส่วนของค่า x และ y เปลี่ยนไปด้วย การปรับ xlim และ ylim ก็เป็นการช่วยปรับสัดส่วนของ x และ y ไปด้วย แต่ว่าแบบนั้นควบคุมสัดส่วนได้ยาก ไหนจะต้องคำนึงถึงขนาดของ figure ด้วย
กรณีที่ต้องการกำหนดสัดส่วนของค่า x และ y ให้แน่นอนอาจใส่คีย์เวิร์ด aspect เพิ่มลงไปในฟังก์ช้น plt.axes
ค่า aspect คือสัดส่วนระหว่างด้านแกน y ต่อแกน x ถ้าใส่เป็น 1 สัดส่วนจะเท่ากัน ถ้าใส่ 0.5 x จะยืดใหญ่กว่า y สองเท่า เป็นต้น
นอกจากใส่เป็นตัวเลขแล้วอาจใส่เป็นสายอักขระ ซึ่งคำที่ใส่ได้คือ equal หมายถึง xy เท่ากัน (=1) และ auto หมายถึงปรับอัตโนมัติ
ตัวอย่าง
theta = np.radians(np.linspace(0,2000,5001))
r = 10*(10+(theta+np.cos(theta**3/100)**2))/(30+theta)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(facecolor='#228899')
plt.axes(aspect=0.5)
plt.plot(x,y,c='#9933AA')
plt.show()
นอกจากนี้ยังอาจปรับได้ทีหลังด้วยเมธอด set_aspect
เช่นลองพิมพ์ลงไปตามนี้แล้วกลับไปดูที่ภาพอีกทีก็จะพบว่ากลายเป็นสัดส่วนเท่ากัน
ax = plt.gca()
ax.set_aspect('equal')
การปรับขอบเขต axes ภายใน figure ในตัวอย่างที่ผ่านมาเราจะเห็นว่าขนาดของกราฟจะถูกกำหนดตายตัว ซึ่งบางทีอาจรู้สึกว่าเหลือพื้นที่ขอบมากเกินไปใช้ไม่คุ้ม
หากต้องการปรับ axes ได้อย่างอิสระให้ใส่อาร์กิวเมนต์ตัวแรกลงไปภายใน plt.axes ก่อนที่จะใส่คีย์เวิร์ดต่างๆเช่นพวก xlim ylim อย่างที่ผ่านมา
โดยอาร์กิวเมนต์ที่ต้องใส่นั้นคือลิสต์ที่ประกอบไปด้วยค่า [ขอบซ้าย,ขอบล่าง,ความกว้าง,ความสูง] โดยทั้งหมดมีหน่วยเป็นสัดส่วนต่อความกว้างและความยาวของภาพทั้งภาพ (ถ้า 1 คือเต็มภาพ)
ตัวอย่าง
theta = np.radians(np.linspace(0,3000,2001))
r = (10+(theta+np.cos(theta**2/10)**2))/(100+theta)
x = r*np.cos(theta)
y = r*np.sin(theta)
plt.figure(figsize=[5,5],facecolor='#66AAEE')
plt.axes([0,0,1,1],xlim=[-0.42,0.42],ylim=[-0.42,0.42])
plt.plot(x,y,c='#99EE11')
plt.show()
แบบนี้จะได้ภาพเต็มจอทั้งหมดเป็นกราฟที่เราวาด ทำให้ไม่เห็นเส้นแกนและขีดกับตัวเลขบอกค่า
ลองปรับลดลงมาหน่อยให้พอเห็น
plt.axes([0.05,0.05,0.93,0.93],xlim=[-0.42,0.42],ylim=[-0.42,0.42])
แบบนี้ก็จะเล็กลงมาจนตัวเลขอยู่ในกรอบ
การเปลี่ยนสีฉากหลัง อีกอย่างที่สามารถเปลี่นได้ก็คือสีฉากหลังของกราฟ ทำได้โดยใส่คีย์เวิร์ด facecolor เพิ่มเข้าไป
ตัวอย่าง
theta = np.radians(np.linspace(0,20000,10001))
x = (10+np.cos(theta*10)/0.5)*np.cos(theta)/(50+theta**1.2)
y = (10+np.cos(theta*10)/0.5)*np.sin(theta)/(50+theta**1.2)
plt.axes(facecolor='#222222',xlim=[-0.16,0.16],ylim=[-0.12,0.12])
plt.plot(x,y,c='#EEEEEE',marker='o',alpha=0.5,ls='-.')
plt.show()
หรืออาจตั้งค่าที่ตัวออบเจ็กต์ axes โดยใช้คำสั่ง set_facecolor ก็ได้เช่นกัน
ส่วนการเปลี่ยนแปลงคุณสมบัติของเส้นแกน เช่นสี ความหนา ก็สามารถทำได้เช่นกัน แต่จะยุ่งยากกว่าเล็กน้อย จะขอยกไปพูดถึงใน
บทที่ ๙ สรุปคีย์เวิร์ดที่ใส่ใน axes เพื่อปรับตั้งค่าต่างๆได้ (เฉพาะที่กล่าวถึงไปแล้วในบทนี้)
คีย์เวิร์ด |
ฟังก์ชัน |
เมธอด |
ความหมาย |
xlim |
plt.xlim |
set_xlim |
ขอบเขตในแกน x |
ylim |
plt.ylim |
set_ylim |
ขอบเขตในแกน y |
xticks |
plt.xticks |
set_xticks |
ค่าตำแหน่งขีดบอกในแกน x |
xticklabels |
set_xticklabels |
ข้อความที่ขีดบอกในแกน x |
yticks |
plt.yticks |
set_yticks |
ค่าตำแหน่งขีดบอกในแกน y |
yticklabels |
set_yticklabels |
ข้อความที่ขีดบอกในแกน y |
aspect |
- |
set_aspect |
สัดส่วนค่าแกน y ต่อ x |
facecolor |
- |
set_facecolor |
สีฉากหลัง |
สรุปเนื้อหา จบบทนี้เราก็สามารถปรับแต่งอะไรได้หลากหลายมากมายแล้ว แต่ก็ยังไม่หมดแค่นั้น ยังมีลูกเล่นอีกมากมายที่สามารถทำได้ใน matplotlib
จะเห็นได้ว่าวิธีการปรับแต่งแกนกราฟนั้นมีอยู่หลากหลายวิธี จะเลือกใช้วิธีไหนขึ้นอยู่กับความสะดวก
เช่นเราอาจใส่คีย์เวิร์ด xticks, xticklabels, ฯลฯ ลงไปในวงเล็บ () หลัง plt.axes พร้อมกันทีเดียวหรือจะใช้ plt.gca() เอาตัวออบเจ็กต์ axes มาปรับค่าด้วยเมธอด set_ ต่างๆที่ตัวออบเจ็กต์นั้นภายหลังก็ได้ หรืออาจใช้ฟังก์ชันเช่น plt.xlim หรือ plt.xticks ก็ได้
อย่างไรก็ตาม การปรับแต่งค่าต่างๆเป็นคีย์เวิร์ดลงใน plt.axes นั้นก็มีข้อจำกัด หากต้องการปรับในรายละเอียดมากขึ้นไปอีกแล้วยังจะมีหลายอย่างที่ยังต้องมาปรับเอาทีหลังด้วยเมธอดหรือฟังก์ชันอื่นๆ ถ้าได้เห็นตัวอย่างในบทถัดๆไปจะเห็นภาพมากขึ้น
อ้างอิง