φυβλαςのβλογ
phyblas的博客



numpy & matplotlib เบื้องต้น บทที่ ๗: การปรับแต่งส่วนประกอบของกราฟ
เขียนเมื่อ 2016/06/11 13:36
แก้ไขล่าสุด 2022/07/21 20:02
หลังจากที่บทที่แล้วได้เรียนรู้ส่วนประกอบของฉากที่ใช้กราฟไปแล้ว คราวนี้จะมาลองดูวิธีการปรับแต่งต่างๆ



การปรับขนาดของภาพ
ในตัวอย่างในบทที่ผ่านๆมาเราวาดกราฟโดยที่ไม่ได้กำหนดขนาด ซึ่งจะเห็นว่ากราฟที่ได้ออกมามีขนาดเป็นค่ามาตรฐานค่าหนึ่ง

เช่นลอง
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 นั้นก็มีข้อจำกัด หากต้องการปรับในรายละเอียดมากขึ้นไปอีกแล้วยังจะมีหลายอย่างที่ยังต้องมาปรับเอาทีหลังด้วยเมธอดหรือฟังก์ชันอื่นๆ ถ้าได้เห็นตัวอย่างในบทถัดๆไปจะเห็นภาพมากขึ้น



อ้างอิง


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


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

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

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

หมวดหมู่

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

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

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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